3 # Copyright 2007 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
21 """App identity stub service implementation.
23 This service behaves the same as the production service, except using
24 constant values instead of app-specific values:
25 * Signing key is constant; in production this rotates.
26 * Public key is constant; in production this varies per app.
27 * Service account name is constant; in production this varies per app.
41 from Crypto
.Hash
import SHA256
42 from Crypto
.PublicKey
import RSA
43 from Crypto
.Util
import number
44 CRYPTO_LIB_INSTALLED
= True
45 except ImportError, e
:
46 CRYPTO_LIB_INSTALLED
= False
48 from google
.appengine
.api
import apiproxy_stub
50 APP_SERVICE_ACCOUNT_NAME
= 'test@localhost'
51 APP_DEFAULT_GCS_BUCKET_NAME
= 'app_default_bucket'
53 SIGNING_KEY_NAME
= 'key'
56 N
= 19119371788959611760073322421014045870056498252163411380847152703712917776733759011400972099255719579701566470175077491500050513917658074590935646529525468755348555932670175295728802986097707368373781743941167574738113348515272061138933984990014969297930973127363812200790406743271047572192133912023914306041356562363557723417403707408838823620411045628159183655215061768071407845537324145892973481372872161981015237572556138317222082306397041309823528068650373958169977675424007883635551170458356632131122901683151395297447872184074888239102348331222079943386530179883880518236689216575776729057173406091195993394637
61 D
= 16986504444572720056487621821047100642841595850137583213470349776864799280835251113078612103869013355016302383270733509621770011190160658118800356360958694229960556902751935956316359959542321272425222634888969943798180994410031448370776358545990991384123912313866752051562052322103544805811361355593091450379904792608637886965065110019212136239200637553477192566763015004249754677600683846556806159369233241157779976231822757855748068765507787598014034587835400718727569389998321277712761796543890788269130617890866139616903097422259980026836628018133574943835504630997228592718738382001678104796538128020421537193913
62 X509_PUBLIC_CERT
= """
63 -----BEGIN CERTIFICATE-----
64 MIIC/jCCAeagAwIBAgIIQTBFcRw3moMwDQYJKoZIhvcNAQEFBQAwIjEgMB4GA1UE
65 AxMXcm9ib3RqYXZhLmEuYXBwc3BvdC5jb20wHhcNMTEwMjIzMTUwNzQ5WhcNMTEw
66 MjI0MTYwNzQ5WjAiMSAwHgYDVQQDExdyb2JvdGphdmEuYS5hcHBzcG90LmNvbTCC
67 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJd0YJCQWvQMa+7L/orCt3D0
68 hVtkdAkeGSikuT4U7mNrxBuOaAbxCIGhRbUe2p+uvRF6MZtLvoU1h9qEFo/wAVDO
69 HN4WHhw3VLl/OVuredRfe8bBTi0KqdgUBrKr8V61n26N3B4Ma9dkTMbcODC/XCfP
70 IRJnTIf4Z1vnoEfWQEJDfW9QLJFyJF17hpp9l5S1uuMJBxjYMsZ3ExLqSFhM7IbN
71 1PDBAb6zGtI7b9AVP+gxS1hjXiJoZA32IWINAZiPV+0k925ecsV0BkI0zV4Ta06F
72 JexNx040y5ivr4C214GRUM3UKihirTcEOBS1a7SRi5wCPh/wT0A8gN6NNbTNjc0C
73 AwEAAaM4MDYwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/
74 BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADggEBAD+h2D+XGIHWMwPCA2DN
75 JgMhN1yTTJ8dtwbiQIhfy8xjOJbrzZaSEX8g2gDm50qaEl5TYHHr2zvAI1UMWdR4
76 nx9TN7I9u3GoOcQsmn9TaOKkBDpMv8sPtFBal3AR5PwR5Sq8/4L/M22LX/TN0eIF
77 Y4LnkW+X/h442N8a1oXn05UYtFo+p/6emZb1S84WZAnONGtF5D1Z6HuX4ikDI5m+
78 iZbwm47mLkV8yuTZGKI1gJsWmAsElPkoWVy2X0t69ecBOYyn3wMmQhkLk2+7lLlD
79 /c4kygP/941fe1Wb/T9yGeBXFwEvJ4jWbX93Q4Xhk9UgHlso9xkCu9QeWFvJqufR
81 -----END CERTIFICATE-----
85 PREFIX
= '3031300d060960864801650304020105000420'
92 LENGTH_OF_SHA256_HASH
= 32
95 class AppIdentityServiceStub(apiproxy_stub
.APIProxyStub
):
96 """A stub for the AppIdentityService API for offline development.
98 Provides stub functions which allow a developer to test integration before
103 def __init__(self
, service_name
='app_identity_service'):
105 super(AppIdentityServiceStub
, self
).__init
__(service_name
)
106 self
.__default
_gcs
_bucket
_name
= APP_DEFAULT_GCS_BUCKET_NAME
108 def _Dynamic_SignForApp(self
, request
, response
):
109 """Implementation of AppIdentityService::SignForApp."""
110 if not CRYPTO_LIB_INSTALLED
:
111 raise NotImplementedError("""Unable to import the pycrypto module,
112 SignForApp is disabled.""")
113 rsa_obj
= RSA
.construct((N
, E
, D
))
114 hashObj
= SHA256
.new()
115 hashObj
.update(request
.bytes_to_sign())
116 padding_length
= MODULUS_BYTES
- LEN_OF_PREFIX
- LENGTH_OF_SHA256_HASH
- 3
117 emsa
= (HEADER1
+ (PADDING
* padding_length
) + HEADER2
+
118 PREFIX
+ hashObj
.hexdigest())
119 sig
= rsa_obj
.sign(binascii
.a2b_hex(emsa
), '')
120 response
.set_signature_bytes(number
.long_to_bytes(sig
[0]))
121 response
.set_key_name(SIGNING_KEY_NAME
)
123 def _Dynamic_GetPublicCertificatesForApp(self
, request
, response
):
124 """Implementation of AppIdentityService::GetPublicCertificatesForApp"""
125 cert
= response
.add_public_certificate_list()
126 cert
.set_key_name(SIGNING_KEY_NAME
)
127 cert
.set_x509_certificate_pem(X509_PUBLIC_CERT
)
129 def _Dynamic_GetServiceAccountName(self
, request
, response
):
130 """Implementation of AppIdentityService::GetServiceAccountName"""
131 response
.set_service_account_name(APP_SERVICE_ACCOUNT_NAME
)
133 def _Dynamic_GetDefaultGcsBucketName(self
, unused_request
, response
):
134 """Implementation of AppIdentityService::GetDefaultGcsBucketName."""
135 response
.set_default_gcs_bucket_name(self
.__default
_gcs
_bucket
_name
)
137 def SetDefaultGcsBucketName(self
, default_gcs_bucket_name
):
138 if default_gcs_bucket_name
:
139 self
.__default
_gcs
_bucket
_name
= default_gcs_bucket_name
141 self
.__default
_gcs
_bucket
_name
= APP_DEFAULT_GCS_BUCKET_NAME
143 def _Dynamic_GetAccessToken(self
, request
, response
):
144 """Implementation of AppIdentityService::GetAccessToken.
146 This API returns an invalid token, as the dev_appserver does not have
147 access to an actual service account.
149 token
= ':'.join(request
.scope_list())
150 service_account_id
= request
.service_account_id()
151 if service_account_id
:
152 token
+= '.%d' % service_account_id
153 if request
.has_service_account_name():
154 token
+= '.%s' % request
.service_account_name()
155 response
.set_access_token('InvalidToken:%s:%s' % (token
, time
.time() % 100))
157 response
.set_expiration_time(int(time
.time()) + 1800)
160 def Create(email_address
=None, private_key_path
=None):
162 from google
.appengine
.api
.app_identity
import app_identity_keybased_stub
164 return app_identity_keybased_stub
.KeyBasedAppIdentityServiceStub(
165 email_address
=email_address
,
166 private_key_path
=private_key_path
)
168 return AppIdentityServiceStub()