Skip to content

Commit a6fda4f

Browse files
committed
Merge remote-tracking branch 'upstream/master' into v0.6.1
2 parents b48fbc7 + 09188e1 commit a6fda4f

13 files changed

+867
-21
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 0.6.1 (July 12th, 2018)
4+
5+
Merge changes of version 0.6.1 of hvac (Python 2/3 client for HashiCorp Vault), see https://github.com/ianunruh/hvac
6+
* see https://github.com/ianunruh/hvac/releases for change logs.
7+
38
## 0.6.0 (July 1, 2018)
49

510
Merge changes of version 0.6.0 of hvac (Python 2/3 client for HashiCorp Vault), see https://github.com/ianunruh/hvac

README.md

+20
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ client = async_hvac.AsyncClient(url='https://localhost:8200')
3636
# Using TLS with client-side certificate authentication
3737
client = async_hvac.AsyncClient(url='https://localhost:8200',
3838
cert=('path/to/cert.pem', 'path/to/key.pem'))
39+
# Skipping TLS verification entirely (should only be used for local development; unsafe for production clusters)
40+
client = async_hvac.AsyncClient(url='https://localhost:8200', verify=False)
3941
```
4042

4143
### Read and write to secret backends
@@ -74,6 +76,24 @@ client.auth_aws_iam(credentials.access_key, credentials.secret_key, credentials.
7476
# GitHub
7577
await client.auth_github('MY_GITHUB_TOKEN')
7678

79+
# GCP (from GCE instance)
80+
import requests
81+
82+
VAULT_ADDR="https://vault.example.com:8200"
83+
ROLE="example"
84+
AUDIENCE_URL = VAULT_ADDR + "/vault/" + ROLE
85+
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}
86+
FORMAT = 'full'
87+
88+
url = 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience={}&format={}'.format(AUDIENCE_URL, FORMAT)
89+
r = requests.get(url, headers=METADATA_HEADERS)
90+
client.auth_gcp(ROLE, r.text)
91+
92+
# Kubernetes (from k8s pod)
93+
f = open('/var/run/secrets/kubernetes.io/serviceaccount/token')
94+
jwt = f.read()
95+
client.auth_kubernetes("example", jwt)
96+
7797
# LDAP, Username & Password
7898
await client.auth_ldap('MY_USERNAME', 'MY_PASSWORD')
7999
await client.auth_userpass('MY_USERNAME', 'MY_PASSWORD')

async_hvac/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ class VaultDown(VaultError):
4242

4343
class UnexpectedError(VaultError):
4444
pass
45+
46+
47+
class ParamValidationError(VaultError):
48+
pass

async_hvac/tests/test_auth_methods.py

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ async def test_tune_auth_backend(self, requests_mocker):
3838
first=test_description,
3939
second=actual_request_params['description'],
4040
)
41+
await client.close()
4142

4243
@RequestsMocker()
4344
async def test_get_auth_backend_tuning(self, requests_mocker):
@@ -77,3 +78,4 @@ async def test_get_auth_backend_tuning(self, requests_mocker):
7778
first=mock_response,
7879
second=actual_response,
7980
)
81+
await client.close()

async_hvac/tests/test_aws_ec2_methods.py

+12
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ async def test_auth_ec2(self, test_label, mount_point, requests_mocker):
6565

6666
# ensure we received our mock response data back successfully
6767
self.assertEqual(mock_response, actual_response)
68+
await client.close()
6869

6970
@parameterized.expand([
7071
("default mount point", None),
@@ -101,6 +102,7 @@ async def test_create_vault_ec2_client_configuration(self, test_label, mount_poi
101102
first=expected_status_code,
102103
second=actual_response.status
103104
)
105+
await client.close()
104106

105107
@parameterized.expand([
106108
("default mount point", None),
@@ -141,6 +143,7 @@ async def test_get_vault_ec2_client_configuration(self, test_label, mount_point,
141143
first=mock_response,
142144
second=actual_response,
143145
)
146+
await client.close()
144147

145148
@parameterized.expand([
146149
("default mount point", None),
@@ -170,6 +173,7 @@ async def test_delete_vault_ec2_client_configuration(self, test_label, mount_poi
170173
first=expected_status_code,
171174
second=actual_response.status,
172175
)
176+
await client.close()
173177

174178
@parameterized.expand([
175179
("default mount point", None, 'my-cool-cert-1'),
@@ -206,6 +210,7 @@ async def test_create_vault_ec2_certificate_configuration(self, test_label, moun
206210
first=expected_status_code,
207211
second=actual_response.status,
208212
)
213+
await client.close()
209214

210215
@parameterized.expand([
211216
("default mount point", None, 'my-cool-cert-1'),
@@ -246,6 +251,7 @@ async def test_get_vault_ec2_certificate_configuration(self, test_label, mount_p
246251
first=mock_response,
247252
second=actual_response,
248253
)
254+
await client.close()
249255

250256
@parameterized.expand([
251257
("default mount point", None),
@@ -284,6 +290,7 @@ async def test_list_vault_ec2_certificate_configurations(self, test_label, mount
284290
first=mock_response,
285291
second=actual_response,
286292
)
293+
await client.close()
287294

288295
@parameterized.expand([
289296
("default mount point", None, 'my-role-1'),
@@ -317,6 +324,7 @@ async def test_create_ec2_role(self, test_label, mount_point, role_name, request
317324
first=expected_status_code,
318325
second=actual_response.status,
319326
)
327+
await client.close()
320328

321329
@parameterized.expand([
322330
("default mount point", None, 'my-role-1'),
@@ -365,6 +373,7 @@ async def test_get_ec2_role(self, test_label, mount_point, role_name, requests_m
365373
first=mock_response,
366374
second=actual_response,
367375
)
376+
await client.close()
368377

369378
@parameterized.expand([
370379
("default mount point", None, 'my-role-1'),
@@ -398,6 +407,7 @@ async def test_delete_ec2_role(self, test_label, mount_point, role_name, request
398407
first=expected_status_code,
399408
second=actual_response.status,
400409
)
410+
await client.close()
401411

402412
@parameterized.expand([
403413
("default mount point", None),
@@ -436,6 +446,7 @@ async def test_list_ec2_roles(self, test_label, mount_point, requests_mocker):
436446
first=mock_response,
437447
second=actual_response,
438448
)
449+
await client.close()
439450

440451
@parameterized.expand([
441452
("default mount point", None, 'my-role-1'),
@@ -476,3 +487,4 @@ async def test_create_ec2_role_tag(self, test_label, mount_point, role_name, req
476487
first=mock_response,
477488
second=await actual_response.json(),
478489
)
490+
await client.close()

async_hvac/tests/test_aws_iam_methods.py

+1
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ async def test_auth_aws_iam(self, auth_mock, datetime_mock):
4646

4747
actual_role = actual_params['role']
4848
self.assertEqual('', actual_role)
49+
await client.close()

async_hvac/tests/test_client.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from asynctest import TestCase
2+
3+
from parameterized import parameterized
4+
5+
from async_hvac import AsyncClient
6+
from async_hvac.tests.util import RequestsMocker
7+
8+
9+
class TestClient(TestCase):
10+
"""Unit tests providing coverage for requests-related methods in the hvac Client class."""
11+
12+
@parameterized.expand([
13+
("standard Vault address", 'https://localhost:8200'),
14+
("Vault address with route", 'https://example.com/vault'),
15+
])
16+
@RequestsMocker()
17+
async def test___request(self, test_label, test_url, requests_mocker):
18+
test_path = 'v1/sys/health'
19+
expected_status_code = 200
20+
mock_url = '{0}/{1}'.format(test_url, test_path)
21+
requests_mocker.register_uri(
22+
method='GET',
23+
url=mock_url,
24+
)
25+
client = AsyncClient(url=test_url)
26+
response = await client._get(
27+
url='v1/sys/health',
28+
)
29+
self.assertEqual(
30+
first=expected_status_code,
31+
second=response.status,
32+
)
33+
await client.close()

async_hvac/tests/test_gcp_methods.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from asynctest import TestCase
2+
3+
from parameterized import parameterized
4+
5+
from async_hvac import AsyncClient
6+
from async_hvac.tests.util import RequestsMocker
7+
8+
9+
class TestGcpMethods(TestCase):
10+
"""Unit tests providing coverage for GCP auth backend-related methods/routes."""
11+
12+
@parameterized.expand([
13+
("default mount point", "custom_role", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", None),
14+
("custom mount point", "custom_role", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", "gcp-not-default")
15+
])
16+
@RequestsMocker()
17+
async def test_auth_gcp(self, test_label, test_role, test_jwt, mount_point, requests_mocker):
18+
mock_response = {
19+
'auth': {
20+
'accessor': 'accessor-1234-5678-9012-345678901234',
21+
'client_token': 'cltoken-1234-5678-9012-345678901234',
22+
'lease_duration': 10000,
23+
'metadata': {
24+
'role': 'custom_role',
25+
'service_account_email': '[email protected]',
26+
'service_account_id': '111111111111111111111'
27+
},
28+
'policies': [
29+
'default',
30+
'custom_role'
31+
],
32+
'renewable': True
33+
},
34+
'data': None,
35+
'lease_duration': 0,
36+
'lease_id': '',
37+
'renewable': False,
38+
'request_id': 'requesti-1234-5678-9012-345678901234',
39+
'warnings': [],
40+
'wrap_info': None
41+
}
42+
mock_url = 'http://127.0.0.1:8200/v1/auth/{0}/login'.format(
43+
'gcp' if mount_point is None else mount_point)
44+
requests_mocker.register_uri(
45+
method='POST',
46+
url=mock_url,
47+
json=mock_response
48+
)
49+
client = AsyncClient()
50+
51+
if mount_point is None:
52+
actual_response = await client.auth_gcp(
53+
role=test_role,
54+
jwt=test_jwt
55+
)
56+
else:
57+
actual_response = await client.auth_gcp(
58+
role=test_role,
59+
jwt=test_jwt,
60+
mount_point=mount_point
61+
)
62+
63+
# ensure we received our mock response data back successfully
64+
self.assertEqual(mock_response, actual_response)
65+
await client.close()

0 commit comments

Comments
 (0)