Skip to content

Commit aeb5012

Browse files
k0kasmarcet
andauthored
Application credentials (#380)
* add endpoints to create/get/remove application credentials * add token creation using application credentials * cancel running workflows on new commit --------- Co-authored-by: smarcet <[email protected]> Co-authored-by: k0ka <[email protected]>
1 parent 7651038 commit aeb5012

23 files changed

+568
-26
lines changed

.github/workflows/integration_tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ on:
77
branches:
88
- master
99

10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
12+
cancel-in-progress: true
13+
1014
jobs:
1115
tests:
1216
if: |

.github/workflows/unit_tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
branches:
77
- master
88

9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
11+
cancel-in-progress: true
12+
913
jobs:
1014
tests:
1115
runs-on: ubuntu-22.04
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Application Credentials
2+
=======================
3+
4+
Add application credential
5+
--------------------------
6+
7+
.. sample:: Identity/v3/application_credentials/add_application_credentials.php
8+
9+
Show application credential details
10+
-----------------------------------
11+
12+
.. sample:: Identity/v3/application_credentials/show_application_credentials.php
13+
14+
Delete application credential
15+
-----------------------------
16+
17+
.. sample:: Identity/v3/application_credentials/delete_application_credentials.php

doc/services/identity/v3/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Identity v3
44
.. toctree::
55
:maxdepth: 3
66

7+
application-credentials
78
credentials
89
domains
910
endpoints

doc/services/identity/v3/tokens.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ Generate token with username
1717

1818
.. sample:: Identity/v3/tokens/generate_token_with_username.php
1919

20+
Generate token with application credential ID
21+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22+
23+
.. sample:: Identity/v3/tokens/generate_token_with_application_credential_id.php
24+
25+
2026
Generate token from ID
2127
~~~~~~~~~~~~~~~~~~~~~~
2228

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => [
13+
'project' => [
14+
'id' => '{projectId}'
15+
]
16+
]
17+
]);
18+
19+
$identity = $openstack->identityV3(['region' => '{region}']);
20+
21+
$user = $identity->getUser('{userId}');
22+
$applicationCredential = $user->createApplicationCredential([
23+
'name' => '{name}',
24+
'description' => '{description}',
25+
]);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => [
13+
'project' => [
14+
'id' => '{projectId}'
15+
]
16+
]
17+
]);
18+
19+
$identity = $openstack->identityV3(['region' => '{region}']);
20+
21+
$user = $identity->getUser('{userId}');
22+
$applicationCredential = $user->getApplicationCredential('{applicationCredentialId}');
23+
$applicationCredential->delete();
24+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => [
13+
'project' => [
14+
'id' => '{projectId}'
15+
]
16+
]
17+
]);
18+
19+
$identity = $openstack->identityV3(['region' => '{region}']);
20+
21+
$user = $identity->getUser('{userId}');
22+
$applicationCredential = $user->getApplicationCredential('{applicationCredentialId}');
23+
$applicationCredential->retrieve();
24+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
$openstack = new OpenStack\OpenStack([
6+
'authUrl' => '{authUrl}',
7+
'region' => '{region}',
8+
'user' => [
9+
'id' => '{userId}',
10+
'password' => '{password}'
11+
],
12+
'scope' => [
13+
'project' => ['id' => '{projectId}']
14+
]
15+
]);
16+
17+
$identity = $openstack->identityV3();
18+
19+
$token = $identity->generateToken([
20+
'application_credential' => [
21+
'id' => '{applicationCredentialId}',
22+
'secret' => '{secret}'
23+
]
24+
]);

samples/Identity/v3/tokens/generate_token_with_username.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@
1818
$identity = $openstack->identityV3();
1919

2020
// Since usernames will not be unique across an entire OpenStack installation,
21-
// when authenticating with them you must also provide your domain ID. You do
21+
// when authenticating with them, you must also provide your domain ID. You do
2222
// not have to do this if you authenticate with a user ID.
23-
2423
$token = $identity->generateToken([
2524
'user' => [
2625
'name' => '{username}',

src/Identity/v3/Api.php

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ public function postTokens(): array
1919
'method' => 'POST',
2020
'path' => 'auth/tokens',
2121
'params' => [
22-
'methods' => $this->params->methods(),
23-
'user' => $this->params->user(),
24-
'tokenId' => $this->params->tokenBody(),
25-
'scope' => $this->params->scope(),
22+
'methods' => $this->params->methods(),
23+
'user' => $this->params->user(),
24+
'application_credential' => $this->params->applicationCredential(),
25+
'tokenId' => $this->params->tokenBody(),
26+
'scope' => $this->params->scope(),
2627
],
2728
];
2829
}
@@ -837,4 +838,43 @@ public function deletePolicy(): array
837838
'params' => ['id' => $this->params->idUrl('policy')],
838839
];
839840
}
841+
842+
public function getApplicationCredential(): array
843+
{
844+
return [
845+
'method' => 'GET',
846+
'path' => 'users/{userId}/application_credentials/{id}',
847+
'jsonKey' => 'application_credential',
848+
'params' => [
849+
'id' => $this->params->idUrl('application_credential'),
850+
'userId' => $this->params->idUrl('user'),
851+
],
852+
];
853+
}
854+
855+
public function postApplicationCredential(): array
856+
{
857+
return [
858+
'method' => 'POST',
859+
'path' => 'users/{userId}/application_credentials',
860+
'jsonKey' => 'application_credential',
861+
'params' => [
862+
'userId' => $this->params->idUrl('user'),
863+
'name' => $this->params->name('application_credential'),
864+
'description' => $this->params->desc('application_credential'),
865+
],
866+
];
867+
}
868+
869+
public function deleteApplicationCredential(): array
870+
{
871+
return [
872+
'method' => 'DELETE',
873+
'path' => 'users/{userId}/application_credentials/{id}',
874+
'params' => [
875+
'id' => $this->params->idUrl('application_credential'),
876+
'userId' => $this->params->idUrl('user'),
877+
],
878+
];
879+
}
840880
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace OpenStack\Identity\v3\Models;
4+
5+
use OpenStack\Common\Resource\Creatable;
6+
use OpenStack\Common\Resource\Deletable;
7+
use OpenStack\Common\Resource\Listable;
8+
use OpenStack\Common\Resource\OperatorResource;
9+
use OpenStack\Common\Resource\Retrievable;
10+
11+
/**
12+
* @property \OpenStack\Identity\v3\Api $api
13+
*/
14+
class ApplicationCredential extends OperatorResource implements Creatable, Listable, Retrievable, Deletable
15+
{
16+
/** @var string */
17+
public $id;
18+
19+
/** @var string */
20+
public $userId;
21+
22+
/** @var string */
23+
public $name;
24+
25+
/** @var string */
26+
public $description;
27+
28+
/** @var string|null */
29+
public $secret = null;
30+
31+
protected $aliases = [
32+
'user_id' => 'userId',
33+
];
34+
35+
protected $resourceKey = 'application_credential';
36+
protected $resourcesKey = 'application_credentials';
37+
38+
/**
39+
* {@inheritdoc}
40+
*
41+
* @param array $userOptions {@see \OpenStack\Identity\v3\Api::postApplicationCredential}
42+
*/
43+
public function create(array $userOptions): Creatable
44+
{
45+
$response = $this->execute($this->api->postApplicationCredential(), $userOptions);
46+
47+
return $this->populateFromResponse($response);
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
public function retrieve()
54+
{
55+
$response = $this->execute(
56+
$this->api->getApplicationCredential(),
57+
['id' => $this->id, 'userId' => $this->userId]
58+
);
59+
$this->populateFromResponse($response);
60+
}
61+
62+
/**
63+
* {@inheritdoc}
64+
*/
65+
public function delete()
66+
{
67+
$this->executeWithState($this->api->deleteApplicationCredential());
68+
}
69+
}

src/Identity/v3/Models/Credential.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ class Credential extends OperatorResource implements Creatable, Updateable, Retr
3939
'user_id' => 'userId',
4040
];
4141

42-
public function create(array $data): Creatable
42+
public function create(array $userOptions): Creatable
4343
{
44-
$response = $this->execute($this->api->postCredentials(), $data);
44+
$response = $this->execute($this->api->postCredentials(), $userOptions);
4545

4646
return $this->populateFromResponse($response);
4747
}

src/Identity/v3/Models/Token.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace OpenStack\Identity\v3\Models;
66

7+
use InvalidArgumentException;
78
use OpenStack\Common\Resource\Alias;
89
use OpenStack\Common\Resource\Creatable;
910
use OpenStack\Common\Resource\OperatorResource;
@@ -94,12 +95,17 @@ public function create(array $data): Creatable
9495
if (isset($data['user'])) {
9596
$data['methods'] = ['password'];
9697
if (!isset($data['user']['id']) && empty($data['user']['domain'])) {
97-
throw new \InvalidArgumentException('When authenticating with a username, you must also provide either the domain name or domain ID to which the user belongs to. Alternatively, if you provide a user ID instead, you do not need to provide domain information.');
98+
throw new InvalidArgumentException('When authenticating with a username, you must also provide either the domain name '.'or domain ID to which the user belongs to. Alternatively, if you provide a user ID instead, '.'you do not need to provide domain information.');
99+
}
100+
} elseif (isset($data['application_credential'])) {
101+
$data['methods'] = ['application_credential'];
102+
if (!isset($data['application_credential']['id']) || !isset($data['application_credential']['secret'])) {
103+
throw new InvalidArgumentException('When authenticating with a application_credential, you must provide application credential ID '.' and application credential secret.');
98104
}
99105
} elseif (isset($data['tokenId'])) {
100106
$data['methods'] = ['token'];
101107
} else {
102-
throw new \InvalidArgumentException('Either a user or token must be provided.');
108+
throw new InvalidArgumentException('Either a user, tokenId or application_credential must be provided.');
103109
}
104110

105111
$response = $this->execute($this->api->postTokens(), $data);

src/Identity/v3/Models/User.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,7 @@ public function delete()
8080
*/
8181
public function listGroups(): \Generator
8282
{
83-
$options['id'] = $this->id;
84-
85-
return $this->model(Group::class)->enumerate($this->api->getUserGroups(), $options);
83+
return $this->model(Group::class)->enumerate($this->api->getUserGroups(), ['id' => $this->id]);
8684
}
8785

8886
/**
@@ -92,4 +90,24 @@ public function listProjects(): \Generator
9290
{
9391
return $this->model(Project::class)->enumerate($this->api->getUserProjects(), ['id' => $this->id]);
9492
}
93+
94+
/**
95+
* Creates a new application credential according to the provided options.
96+
*
97+
* @param array $options {@see \OpenStack\Identity\v3\Api::postApplicationCredential}
98+
*/
99+
public function createApplicationCredential(array $options): ApplicationCredential
100+
{
101+
return $this->model(ApplicationCredential::class)->create(['userId' => $this->id] + $options);
102+
}
103+
104+
/**
105+
* Retrieves an application credential object and populates its unique identifier object. This operation will not
106+
* perform a GET or HEAD request by default; you will need to call retrieve() if you want to pull in remote state
107+
* from the API.
108+
*/
109+
public function getApplicationCredential(string $id): ApplicationCredential
110+
{
111+
return $this->model(ApplicationCredential::class, ['id' => $id, 'userId' => $this->id]);
112+
}
95113
}

0 commit comments

Comments
 (0)