blob: 70fa5ca3352ac6552d3f689376dcfa1db527edcc [file] [log] [blame]
Jon Wayne Parrott04714752016-10-24 10:00:58 -07001# Copyright 2016 Google Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import datetime
16
17import mock
18import pytest
19
20from google.auth import app_engine
21
22
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070023class _AppIdentityModule(object):
24 """The interface of the App Idenity app engine module.
25 See https://cloud.google.com/appengine/docs/standard/python/refdocs
26 /google.appengine.api.app_identity.app_identity
27 """
28 def get_application_id(self):
29 raise NotImplementedError()
30
31 def sign_blob(self, bytes_to_sign, deadline=None):
32 raise NotImplementedError()
33
34 def get_service_account_name(self, deadline=None):
35 raise NotImplementedError()
36
37 def get_access_token(self, scopes, service_account_id=None):
38 raise NotImplementedError()
39
40
Jon Wayne Parrott04714752016-10-24 10:00:58 -070041@pytest.fixture
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070042def app_identity(monkeypatch):
Jon Wayne Parrott04714752016-10-24 10:00:58 -070043 """Mocks the app_identity module for google.auth.app_engine."""
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070044 app_identity_module = mock.create_autospec(
45 _AppIdentityModule, instance=True)
Jon Wayne Parrott04714752016-10-24 10:00:58 -070046 monkeypatch.setattr(
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070047 app_engine, 'app_identity', app_identity_module)
48 yield app_identity_module
Jon Wayne Parrott04714752016-10-24 10:00:58 -070049
50
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070051def test_get_project_id(app_identity):
52 app_identity.get_application_id.return_value = mock.sentinel.project
Jon Wayne Parrott2148fde2016-10-24 13:44:25 -070053 assert app_engine.get_project_id() == mock.sentinel.project
54
55
56def test_get_project_id_missing_apis():
57 with pytest.raises(EnvironmentError) as excinfo:
58 assert app_engine.get_project_id()
59
60 assert excinfo.match(r'App Engine APIs are not available')
61
62
Jon Wayne Parrott5b4e9c82017-02-15 16:44:00 -080063class TestSigner(object):
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070064 def test_key_id(self, app_identity):
65 app_identity.sign_blob.return_value = (
Jon Wayne Parrott5b4e9c82017-02-15 16:44:00 -080066 mock.sentinel.key_id, mock.sentinel.signature)
67
68 signer = app_engine.Signer()
69
Jon Wayne Parrott254befe2017-02-22 14:37:31 -080070 assert signer.key_id is None
Jon Wayne Parrott5b4e9c82017-02-15 16:44:00 -080071
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070072 def test_sign(self, app_identity):
73 app_identity.sign_blob.return_value = (
Jon Wayne Parrott5b4e9c82017-02-15 16:44:00 -080074 mock.sentinel.key_id, mock.sentinel.signature)
75
76 signer = app_engine.Signer()
77 to_sign = b'123'
78
79 signature = signer.sign(to_sign)
80
81 assert signature == mock.sentinel.signature
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070082 app_identity.sign_blob.assert_called_with(to_sign)
Jon Wayne Parrott5b4e9c82017-02-15 16:44:00 -080083
84
Jon Wayne Parrott04714752016-10-24 10:00:58 -070085class TestCredentials(object):
86 def test_missing_apis(self):
87 with pytest.raises(EnvironmentError) as excinfo:
88 app_engine.Credentials()
89
90 assert excinfo.match(r'App Engine APIs are not available')
91
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070092 def test_default_state(self, app_identity):
Jon Wayne Parrott04714752016-10-24 10:00:58 -070093 credentials = app_engine.Credentials()
94
95 # Not token acquired yet
96 assert not credentials.valid
97 # Expiration hasn't been set yet
98 assert not credentials.expired
99 # Scopes are required
100 assert not credentials.scopes
101 assert credentials.requires_scopes
102
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700103 def test_with_scopes(self, app_identity):
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700104 credentials = app_engine.Credentials()
105
106 assert not credentials.scopes
107 assert credentials.requires_scopes
108
109 scoped_credentials = credentials.with_scopes(['email'])
110
111 assert scoped_credentials.has_scopes(['email'])
112 assert not scoped_credentials.requires_scopes
113
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700114 def test_service_account_email_implicit(self, app_identity):
115 app_identity.get_service_account_name.return_value = (
Jon Wayne Parrott61ffb052016-11-08 09:30:30 -0800116 mock.sentinel.service_account_email)
117 credentials = app_engine.Credentials()
118
119 assert (credentials.service_account_email ==
120 mock.sentinel.service_account_email)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700121 assert app_identity.get_service_account_name.called
Jon Wayne Parrott61ffb052016-11-08 09:30:30 -0800122
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700123 def test_service_account_email_explicit(self, app_identity):
Jon Wayne Parrott61ffb052016-11-08 09:30:30 -0800124 credentials = app_engine.Credentials(
125 service_account_id=mock.sentinel.service_account_email)
126
127 assert (credentials.service_account_email ==
128 mock.sentinel.service_account_email)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700129 assert not app_identity.get_service_account_name.called
Jon Wayne Parrott61ffb052016-11-08 09:30:30 -0800130
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700131 @mock.patch(
132 'google.auth._helpers.utcnow',
Jon Wayne Parrott7af9f662017-05-08 09:40:56 -0700133 return_value=datetime.datetime.min)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700134 def test_refresh(self, utcnow, app_identity):
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700135 token = 'token'
Jon Wayne Parrott1cba0f82017-09-12 10:21:02 -0700136 ttl = 643942923
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700137 app_identity.get_access_token.return_value = token, ttl
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700138 credentials = app_engine.Credentials(scopes=['email'])
139
140 credentials.refresh(None)
141
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700142 app_identity.get_access_token.assert_called_with(
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700143 credentials.scopes, credentials._service_account_id)
144 assert credentials.token == token
Jon Wayne Parrott1cba0f82017-09-12 10:21:02 -0700145 assert credentials.expiry == datetime.datetime(
146 1990, 5, 29, 1, 2, 3)
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700147 assert credentials.valid
148 assert not credentials.expired
149
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700150 def test_sign_bytes(self, app_identity):
151 app_identity.sign_blob.return_value = (
Jon Wayne Parrott5b4e9c82017-02-15 16:44:00 -0800152 mock.sentinel.key_id, mock.sentinel.signature)
Jon Wayne Parrott04714752016-10-24 10:00:58 -0700153 credentials = app_engine.Credentials()
154 to_sign = b'123'
155
156 signature = credentials.sign_bytes(to_sign)
157
158 assert signature == mock.sentinel.signature
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700159 app_identity.sign_blob.assert_called_with(to_sign)
Jon Wayne Parrott4c883f02016-12-02 14:26:33 -0800160
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700161 def test_signer(self, app_identity):
Jon Wayne Parrottd7221672017-02-16 09:05:11 -0800162 credentials = app_engine.Credentials()
163 assert isinstance(credentials.signer, app_engine.Signer)
164
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700165 def test_signer_email(self, app_identity):
Jon Wayne Parrott4c883f02016-12-02 14:26:33 -0800166 credentials = app_engine.Credentials()
167 assert credentials.signer_email == credentials.service_account_email