Skip to content

[Python] Support for HTTP signature #4958

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 128 commits into from
Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
128 commits
Select commit Hold shift + click to select a range
846b9ba
start implementation of HTTP signature
sebastien-rosset Dec 29, 2019
64733bd
add api key parameters for http message signature
sebastien-rosset Jan 2, 2020
b151f20
HTTP signature authentication
sebastien-rosset Jan 6, 2020
1cdc6ab
start implementation of HTTP signature
sebastien-rosset Dec 29, 2019
c2fdefa
add api key parameters for http message signature
sebastien-rosset Jan 2, 2020
32a3647
HTTP signature authentication
sebastien-rosset Jan 6, 2020
2d000e4
sync from master
sebastien-rosset Jan 6, 2020
1ef838b
HTTP signature authentication
sebastien-rosset Jan 6, 2020
3246c1d
start implementation of HTTP signature
sebastien-rosset Dec 29, 2019
4b33ef8
fix merge issues
sebastien-rosset Jan 6, 2020
52aecf8
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 13, 2020
2d63a3a
Address formatting issues
sebastien-rosset Jan 13, 2020
409ac38
Address formatting issues
sebastien-rosset Jan 13, 2020
2bf6f1a
move python-experimental-openapiv3-sample to a separate PR
sebastien-rosset Jan 13, 2020
d626293
Add support for HTTP signature
sebastien-rosset Jan 13, 2020
9eca52c
Add code comments
sebastien-rosset Jan 13, 2020
a59f759
Add code comments
sebastien-rosset Jan 13, 2020
b6e3b0c
merge from http-signature branch
sebastien-rosset Jan 13, 2020
16c1891
Fix formatting issues
sebastien-rosset Jan 13, 2020
a1a181c
Fix formatting issues
sebastien-rosset Jan 13, 2020
7f1c4cf
Fix formatting issues
sebastien-rosset Jan 13, 2020
9e6395f
add code comments
sebastien-rosset Jan 14, 2020
e5616dd
add code comments
sebastien-rosset Jan 14, 2020
d8175a0
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 14, 2020
1b86216
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 14, 2020
9fdb7ef
fix python formatting issues
sebastien-rosset Jan 14, 2020
ae56f20
Make PKCS1v15 string constant consistent between Python and Golang
sebastien-rosset Jan 14, 2020
c4c23b8
fix python formatting issues
sebastien-rosset Jan 14, 2020
8948135
Add code comments in generated Python. Start adding unit tests for HT…
sebastien-rosset Jan 14, 2020
176f130
compliance with HTTP signature draft 12
sebastien-rosset Jan 14, 2020
e4c0e1a
compliance with HTTP signature draft 12
sebastien-rosset Jan 14, 2020
e4cc4df
working on review comments
sebastien-rosset Jan 14, 2020
e5811b0
working on review comments
sebastien-rosset Jan 14, 2020
916416d
working on review comments
sebastien-rosset Jan 14, 2020
7db2a62
working on review comments
sebastien-rosset Jan 14, 2020
fac1af1
working on review comments
sebastien-rosset Jan 14, 2020
e053076
working on review comments
sebastien-rosset Jan 14, 2020
2ef4815
working on review comments
sebastien-rosset Jan 15, 2020
a3e3c72
working on review comments
sebastien-rosset Jan 15, 2020
b56e38f
working on review comments
sebastien-rosset Jan 15, 2020
acfb44d
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 15, 2020
9d81bb7
fix python formatting issues
sebastien-rosset Jan 15, 2020
c4c1530
fix trailing white space
sebastien-rosset Jan 15, 2020
c7a654e
address PR comments
sebastien-rosset Jan 15, 2020
9b9d272
address PR comments
sebastien-rosset Jan 15, 2020
9c4c2fa
address PR comments
sebastien-rosset Jan 15, 2020
08557f4
Add suppport for '(expires)' signature parameter
sebastien-rosset Jan 15, 2020
2eb6264
address PR comments
sebastien-rosset Jan 15, 2020
976b55b
address PR comments
sebastien-rosset Jan 15, 2020
05e6069
Fix python formatting issues
sebastien-rosset Jan 15, 2020
dc55391
Fix python formatting issues
sebastien-rosset Jan 15, 2020
959178a
Starting to move code to dedicated file for HTTP signatures
sebastien-rosset Jan 15, 2020
277e489
Continue to refactor code to dedicated file for HTTP signatures
sebastien-rosset Jan 15, 2020
7fb18e2
Continue to refactor code to dedicated file for HTTP signatures
sebastien-rosset Jan 15, 2020
0713164
Continue to refactor code to dedicated file for HTTP signatures
sebastien-rosset Jan 15, 2020
719146d
Continue to refactor code to dedicated file for HTTP signatures
sebastien-rosset Jan 15, 2020
3151982
move method to ProcessUtils
sebastien-rosset Jan 15, 2020
6fd8432
conditionally build signing.py
sebastien-rosset Jan 15, 2020
bb12421
move method to ProcessUtils
sebastien-rosset Jan 15, 2020
21c478f
Merge branch 'http-signature' of github.com:CiscoM31/openapi-generato…
sebastien-rosset Jan 15, 2020
7c1967e
Code reformatting
sebastien-rosset Jan 16, 2020
2db7093
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 16, 2020
de9124c
externalize http signature configuration
sebastien-rosset Jan 16, 2020
00fd981
address PR review comments
sebastien-rosset Jan 16, 2020
09b9515
address PR review comments
sebastien-rosset Jan 16, 2020
0e4f43c
run samples scripts
sebastien-rosset Jan 16, 2020
c2da37a
Address PR review comments
sebastien-rosset Jan 16, 2020
581e433
Move 'private_key' field to signing module
sebastien-rosset Jan 16, 2020
5f60e2e
Move 'private_key' field to signing module
sebastien-rosset Jan 16, 2020
69d394d
code cleanup
sebastien-rosset Jan 16, 2020
3ee3c0e
remove use of strftime('%s'), which is non portable
sebastien-rosset Jan 16, 2020
7787a7b
code cleanup
sebastien-rosset Jan 16, 2020
8b69dc7
code cleanup
sebastien-rosset Jan 16, 2020
f67523c
code cleanup
sebastien-rosset Jan 16, 2020
d169c6e
run sample scripts
sebastien-rosset Jan 16, 2020
4148453
sync from mater
sebastien-rosset Jan 16, 2020
755335c
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 16, 2020
06d25b9
Address PR review comments.
sebastien-rosset Jan 16, 2020
1bf286f
Add http-signature security scheme
sebastien-rosset Jan 17, 2020
5170195
Run sample scripts for go
sebastien-rosset Jan 17, 2020
de10ae0
Fix issue uncovered in integration branch
sebastien-rosset Jan 17, 2020
0176694
Fix issue uncovered in integration branch
sebastien-rosset Jan 17, 2020
155f554
Fix issue uncovered in integration branch
sebastien-rosset Jan 17, 2020
0426487
Fix issue uncovered in integration branch
sebastien-rosset Jan 17, 2020
6cfefa0
Run samples scripts
sebastien-rosset Jan 17, 2020
c886658
move http signature tests to separate file
sebastien-rosset Jan 17, 2020
c7a01ec
move http signature tests to separate file
sebastien-rosset Jan 17, 2020
3ceda78
unit tests for HTTP signature
sebastien-rosset Jan 17, 2020
707d40b
continue implementation of unit tests
sebastien-rosset Jan 17, 2020
ef59c0c
add http_signature_test to security scheme
sebastien-rosset Jan 17, 2020
9daccca
add unit tests for http signature
sebastien-rosset Jan 17, 2020
5355566
address review comments
sebastien-rosset Jan 17, 2020
0f7cbb1
Merge branch 'master' into http-signature
sebastien-rosset Jan 17, 2020
f8dea28
remove http signature from petapi
sebastien-rosset Jan 17, 2020
d33f6b6
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 17, 2020
aafedc6
Merge branch 'http-signature' into python-http-signature
sebastien-rosset Jan 17, 2020
21e35f0
Add separate OAS file with support for HTTP signature
sebastien-rosset Jan 17, 2020
6ab9cf9
Merge branch 'http-signature' into python-http-signature
sebastien-rosset Jan 17, 2020
7fb5c6e
Add support for private key passphrase. Add more unit tests
sebastien-rosset Jan 17, 2020
5f4d6c6
Add unit test to validate the signature against the public key
sebastien-rosset Jan 17, 2020
daf060e
remove http signature from petstore-with-fake-endpoints-models-for-te…
sebastien-rosset Jan 17, 2020
790c093
Merge branch 'http-signature' into python-http-signature
sebastien-rosset Jan 17, 2020
9f9f6be
fix unit test issues
sebastien-rosset Jan 17, 2020
c4651cf
run scripts in bin directory
sebastien-rosset Jan 18, 2020
57e43fd
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 19, 2020
1b1aef6
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 19, 2020
4f7e6eb
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 19, 2020
b9f2bff
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 19, 2020
7b93f54
Refact unit test with better variable names
sebastien-rosset Jan 19, 2020
066237f
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 20, 2020
34f126f
do not throw exception if security scheme is unrecognized
sebastien-rosset Jan 20, 2020
7b3a54b
change URL of apache license to use https
sebastien-rosset Jan 21, 2020
85d1323
sync from master
sebastien-rosset Jan 22, 2020
6abf380
sync from master
sebastien-rosset Jan 22, 2020
d8b0dc6
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 22, 2020
2d6516e
fix usage of escape character in python regex. Fix generated python d…
sebastien-rosset Jan 22, 2020
a14c506
write HTTP signed headers in user-specified order. Fix PEP8 formattin…
sebastien-rosset Jan 22, 2020
a2b0c84
write HTTP signed headers in user-specified order. Fix PEP8 formattin…
sebastien-rosset Jan 22, 2020
2137cc1
http signature unit tests
sebastien-rosset Jan 23, 2020
e532a67
Fix PEP8 format issue
sebastien-rosset Jan 23, 2020
7d89594
Merge remote-tracking branch 'origin' into http-signature
sebastien-rosset Jan 23, 2020
1bb0df5
Merge branch 'http-signature' into python-http-signature
sebastien-rosset Jan 23, 2020
39a6d01
spread out each requirement to a separate line
sebastien-rosset Jan 23, 2020
15a5c09
run samples scripts
sebastien-rosset Jan 23, 2020
3bcb958
Merge remote-tracking branch 'origin' into python-http-signature
sebastien-rosset Jan 24, 2020
7184320
run sample scripts
sebastien-rosset Jan 24, 2020
45f2cfd
sync from master
sebastien-rosset Jan 26, 2020
4db1b21
remove encoding of '+' character
sebastien-rosset Jan 26, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bin/openapi3/python-experimental-petstore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/python -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g python-experimental -o samples/openapi3/client/petstore/python-experimental/ --additional-properties packageName=petstore_api $@"
#yaml="modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml"
yaml="modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml"
ags="generate -t modules/openapi-generator/src/main/resources/python -i $yaml -g python-experimental -o samples/openapi3/client/petstore/python-experimental/ --additional-properties packageName=petstore_api $@"

java $JAVA_OPTS -jar $executable $ags
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.examples.ExampleGenerator;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.openapitools.codegen.utils.ProcessUtils;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.slf4j.Logger;
Expand Down Expand Up @@ -116,6 +118,14 @@ public void processOpts() {
supportingFiles.add(new SupportingFile("python-experimental/__init__package.mustache", packagePath(), "__init__.py"));


// Generate the 'signing.py' module, but only if the 'HTTP signature' security scheme is specified in the OAS.
Map<String, SecurityScheme> securitySchemeMap = openAPI != null ?
(openAPI.getComponents() != null ? openAPI.getComponents().getSecuritySchemes() : null) : null;
List<CodegenSecurity> authMethods = fromSecurity(securitySchemeMap);
if (ProcessUtils.hasHttpSignatureMethods(authMethods)) {
supportingFiles.add(new SupportingFile("python-experimental/signing.mustache", packagePath(), "signing.py"));
}

Boolean generateSourceCodeOnly = false;
if (additionalProperties.containsKey(CodegenConstants.SOURCECODEONLY_GENERATION)) {
generateSourceCodeOnly = Boolean.valueOf(additionalProperties.get(CodegenConstants.SOURCECODEONLY_GENERATION).toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class Configuration(object):
The dict value is an API key prefix when generating the auth data.
:param username: Username for HTTP basic authentication
:param password: Password for HTTP basic authentication
:param signing_info: Configuration parameters for HTTP signature.
Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration

:Example:

Expand All @@ -49,11 +51,50 @@ class Configuration(object):
)
The following cookie will be added to the HTTP request:
Cookie: JSESSIONID abc123

Configure API client with HTTP basic authentication:
conf = {{{packageName}}}.Configuration(
username='the-user',
password='the-password',
)

Configure API client with HTTP signature authentication. Use the 'hs2019' signature scheme,
sign the HTTP requests with the RSA-SSA-PSS signature algorithm, and set the expiration time
of the signature to 5 minutes after the signature has been created.
Note you can use the constants defined in the {{{packageName}}}.signing module, and you can
also specify arbitrary HTTP headers to be included in the HTTP signature, except for the
'Authorization' header, which is used to carry the signature.

One may be tempted to sign all headers by default, but in practice it rarely works.
This is beccause explicit proxies, transparent proxies, TLS termination endpoints or
load balancers may add/modify/remove headers. Include the HTTP headers that you know
are not going to be modified in transit.

conf = {{{packageName}}}.Configuration(
signing_info = {{{packageName}}}.signing.HttpSigningConfiguration(
key_id = 'my-key-id',
private_key_path = 'rsa.pem',
signing_scheme = signing.SCHEME_HS2019,
signing_algorithm = signing.ALGORITHM_RSASSA_PSS,
signed_headers = [signing.HEADER_REQUEST_TARGET,
signing.HEADER_CREATED,
signing.HEADER_EXPIRES,
signing.HEADER_HOST,
signing.HEADER_DATE,
signing.HEADER_DIGEST,
'Content-Type',
'Content-Length',
'User-Agent'
],
signature_max_validity = datetime.timedelta(minutes=5)
)
)
"""

def __init__(self, host="{{{basePath}}}",
api_key=None, api_key_prefix=None,
username=None, password=None):
username=None, password=None,
signing_info=None):
"""Constructor
"""
self.host = host
Expand Down Expand Up @@ -82,6 +123,11 @@ class Configuration(object):
self.password = password
"""Password for HTTP basic authentication
"""
if signing_info is not None:
signing_info.host = host
self.signing_info = signing_info
"""The HTTP signing configuration
"""
{{#hasOAuthMethods}}
self.access_token = ""
"""access token for OAuth/Bearer
Expand Down Expand Up @@ -318,6 +364,15 @@ class Configuration(object):
'value': 'Bearer ' + self.access_token
}
{{/isBasicBearer}}
{{#isHttpSignature}}
if self.signing_info is not None:
auth['{{name}}'] = {
'type': 'http-signature',
'in': 'header',
'key': 'Authorization',
'value': None # Signature headers are calculated for every HTTP request
}
{{/isHttpSignature}}
{{/isBasic}}
{{#isOAuth}}
if self.access_token is not None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ Class | Method | HTTP request | Description
{{#isBasicBearer}}
- **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
{{/isBasicBearer}}
{{#isHttpSignature}}
- **Type**: HTTP signature authentication
{{/isHttpSignature}}
{{/isBasic}}
{{#isOAuth}}
- **Type**: OAuth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class {{classname}}(object):
{{#-first}}
'auth': [
{{/-first}}
'{{name}}'{{#hasMore}}, {{/hasMore}}
'{{name}}'{{#hasMore}},{{/hasMore}}
{{#-last}}
],
{{/-last}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,14 @@ class ApiClient(object):
collection_formats)
post_params.extend(self.files_parameters(files))

# auth setting
self.update_params_for_auth(header_params, query_params, auth_settings)

# body
if body:
body = self.sanitize_for_serialization(body)

# auth setting
self.update_params_for_auth(header_params, query_params,
auth_settings, resource_path, method, body)

# request url
if _host is None:
url = self.configuration.host + resource_path
Expand Down Expand Up @@ -517,12 +518,17 @@ class ApiClient(object):
else:
return content_types[0]

def update_params_for_auth(self, headers, querys, auth_settings):
def update_params_for_auth(self, headers, querys, auth_settings,
resource_path, method, body):
"""Updates header and query params based on authentication setting.

:param headers: Header parameters dict to be updated.
:param querys: Query parameters tuple list to be updated.
:param auth_settings: Authentication setting identifiers list.
:resource_path: A string representation of the HTTP request resource path.
:method: A string representation of the HTTP request method.
:body: A object representing the body of the HTTP request.
The object type is the return value of sanitize_for_serialization().
"""
if not auth_settings:
return
Expand All @@ -533,7 +539,17 @@ class ApiClient(object):
if auth_setting['in'] == 'cookie':
headers['Cookie'] = auth_setting['value']
elif auth_setting['in'] == 'header':
headers[auth_setting['key']] = auth_setting['value']
if auth_setting['type'] != 'http-signature':
headers[auth_setting['key']] = auth_setting['value']
{{#hasHttpSignatureMethods}}
else:
# The HTTP signature scheme requires multiple HTTP headers
# that are calculated dynamically.
signing_info = self.configuration.signing_info
auth_headers = signing_info.get_http_signature_headers(
resource_path, method, headers, body, querys)
headers.update(auth_headers)
{{/hasHttpSignatureMethods}}
elif auth_setting['in'] == 'query':
querys.append((auth_setting['key'], auth_setting['value']))
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,22 @@ VERSION = "{{packageVersion}}"
# prerequisite: setuptools
# http://pypi.python.org/pypi/setuptools

REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"]
REQUIRES = [
"urllib3 >= 1.15",
"six >= 1.10",
"certifi",
"python-dateutil",
{{#asyncio}}
REQUIRES.append("aiohttp >= 3.0.0")
"aiohttp >= 3.0.0",
{{/asyncio}}
{{#tornado}}
REQUIRES.append("tornado>=4.2,<5")
"tornado>=4.2,<5",
{{/tornado}}
{{#hasHttpSignatureMethods}}
"pem>=19.3.0",
"pycryptodome>=3.9.0",
{{/hasHttpSignatureMethods}}
]
EXTRAS = {':python_version <= "2.7"': ['future']}

setup(
Expand Down
Loading