1d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone# Use of this source code is governed by a BSD-style license that can be
3d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone# found in the LICENSE file.
4d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
53d68fe8213ef86684d7911f889d56d1345bf3272Chris Masoneimport dbus, gobject, sys
6d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
7d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masoneimport common
8d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masonefrom autotest_lib.client.common_lib import error
93d68fe8213ef86684d7911f889d56d1345bf3272Chris Masonefrom autotest_lib.client.common_lib.cros import session_manager
103d68fe8213ef86684d7911f889d56d1345bf3272Chris Masonefrom autotest_lib.client.cros import ownership
11d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
12d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
13d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone"""Utility class for tests that generate, push and fetch policies.
14d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
15d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris MasoneAs the python bindings for the protobufs used in policies are built as a part
16d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masoneof tests that use them, callers must pass in their location at call time."""
17d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
18d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
19d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masonedef compare_policy_response(proto_binding_location, policy_response,
20d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                            owner=None, guests=None, new_users=None,
21d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                            roaming=None, whitelist=None, proxies=None):
22d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """Check the contents of |policy_response| against given args.
23d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
24d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    Deserializes |policy_response| into a PolicyFetchResponse protobuf,
25d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    with an embedded (serialized) PolicyData protobuf that embeds a
26d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    (serialized) ChromeDeviceSettingsProto, and checks to see if this
27d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    protobuf turducken contains the information passed in.
28d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
29d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param proto_binding_location: the location of generated python bindings
30d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                                   for policy protobufs.
31d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param policy_response: string serialization of a PolicyData protobuf.
32d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param owner: string representing the owner's name/account.
33d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param guests: boolean indicating whether guests should be allowed.
34d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param new_users: boolean indicating if user pods are on login screen.
35d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param roaming: boolean indicating whether data roaming is enabled.
36d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param whitelist: list of accounts that are allowed to log in.
37d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param proxies: dictionary - { 'proxy_mode': <string> }
38d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
39d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @return True if |policy_response| has all the provided data, else False.
40d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """
41d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    # Pull in protobuf bindings.
42d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    sys.path.append(proto_binding_location)
43d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from device_management_backend_pb2 import PolicyFetchResponse
44d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from device_management_backend_pb2 import PolicyData
45d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import ChromeDeviceSettingsProto
46d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import AllowNewUsersProto
47d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import GuestModeEnabledProto
48d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import ShowUserNamesOnSigninProto
49d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import DataRoamingEnabledProto
50d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import DeviceProxySettingsProto
51d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
52d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    response_proto = PolicyFetchResponse()
53d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    response_proto.ParseFromString(policy_response)
54d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    ownership.assert_has_policy_data(response_proto)
55d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
56d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    data_proto = PolicyData()
57d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    data_proto.ParseFromString(response_proto.policy_data)
58d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    ownership.assert_has_device_settings(data_proto)
59d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if owner: ownership.assert_username(data_proto, owner)
60d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
61d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    settings = ChromeDeviceSettingsProto()
62d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    settings.ParseFromString(data_proto.policy_value)
63d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if guests: ownership.assert_guest_setting(settings, guests)
64d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if new_users: ownership.assert_show_users(settings, new_users)
65d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if roaming: ownership.assert_roaming(settings, roaming)
66d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if whitelist:
67d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        ownership.assert_new_users(settings, False)
68d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        ownership.assert_users_on_whitelist(settings, whitelist)
69d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        if proxies: ownership.assert_proxy_settings(settings, proxies)
70d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
71d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
72d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masonedef build_policy_data(proto_binding_location, owner=None, guests=None,
73d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                      new_users=None, roaming=None, whitelist=None,
74d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                      proxies=None):
75d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """Generate and serialize a populated device policy protobuffer.
76d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
77d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    Creates a PolicyData protobuf, with an embedded
78d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    ChromeDeviceSettingsProto, containing the information passed in.
79d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
80d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param proto_binding_location: the location of generated python bindings
81d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                                   for policy protobufs.
82d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param owner: string representing the owner's name/account.
83d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param guests: boolean indicating whether guests should be allowed.
84d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param new_users: boolean indicating if user pods are on login screen.
85d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param roaming: boolean indicating whether data roaming is enabled.
86d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param whitelist: list of accounts that are allowed to log in.
87d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param proxies: dictionary - { 'proxy_mode': <string> }
88d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
89d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @return serialization of the PolicyData proto that we build.
90d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """
91d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    # Pull in protobuf bindings.
92d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    sys.path.append(proto_binding_location)
93d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from device_management_backend_pb2 import PolicyData
94d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import ChromeDeviceSettingsProto
95d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import AllowNewUsersProto
96d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import GuestModeEnabledProto
97d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import ShowUserNamesOnSigninProto
98d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import DataRoamingEnabledProto
99d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from chrome_device_policy_pb2 import DeviceProxySettingsProto
100d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
101d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    data_proto = PolicyData()
102d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    data_proto.policy_type = ownership.POLICY_TYPE
103d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if owner: data_proto.username = owner
104d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
105d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    settings = ChromeDeviceSettingsProto()
106d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if guests:
107d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        settings.guest_mode_enabled.guest_mode_enabled = guests
108d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if new_users:
109d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        settings.show_user_names.show_user_names = new_users
110d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if roaming:
111d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        settings.data_roaming_enabled.data_roaming_enabled = roaming
112d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if whitelist:
113d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        settings.allow_new_users.allow_new_users = False
114d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        for user in whitelist:
115d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone            settings.user_whitelist.user_whitelist.append(user)
116d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if proxies:
117d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        settings.device_proxy_settings.proxy_mode = proxies['proxy_mode']
118d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
119d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    data_proto.policy_value = settings.SerializeToString()
120d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    return data_proto.SerializeToString()
121d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
122d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
123d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masonedef generate_policy(proto_binding_location, key, pubkey, policy, old_key=None):
124d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """Generate and serialize a populated, signed device policy protobuffer.
125d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
126d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    Creates a protobuf containing the device policy |policy|, signed with
127d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    |key|.  Also includes the public key |pubkey|, signed with |old_key|
128d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if provided.  If not, |pubkey| is signed with |key|.  The protobuf
129d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    is serialized to a string and returned.
130d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
131d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param proto_binding_location: the location of generated python bindings
132d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                                   for policy protobufs.
133d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param key: new policy signing key.
134d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param pubkey: new public key to be signed and embedded in generated
135d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                   PolicyFetchResponse.
136d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param policy: policy data to be embedded in generated PolicyFetchResponse.
137d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param old_key: if provided, this implies the generated PolicyFetchRespone
138d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                    is intended to represent a key rotation.  pubkey will be
139d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone                    signed with this key before embedding.
140d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
141d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @return serialization of the PolicyFetchResponse proto that we build.
142d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """
143d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    # Pull in protobuf bindings.
144d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    sys.path.append(proto_binding_location)
145d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    from device_management_backend_pb2 import PolicyFetchResponse
146d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
147d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if old_key == None:
148d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        old_key = key
149d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    policy_proto = PolicyFetchResponse()
150d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    policy_proto.policy_data = policy
151d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    policy_proto.policy_data_signature = ownership.sign(key, policy)
152d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    policy_proto.new_public_key = pubkey
153d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    policy_proto.new_public_key_signature = ownership.sign(old_key, pubkey)
154d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    return policy_proto.SerializeToString()
155d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
156d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
157d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masonedef push_policy_and_verify(policy_string, sm):
158d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """Push a device policy to the session manager over DBus.
159d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
160d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    The serialized device policy |policy_string| is sent to the session
161d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    manager with the StorePolicy DBus call.  Success of the store is
162d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    validated by fetching the policy again and comparing.
163d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
164d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param policy_string: serialized policy to push to the session manager.
165d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param sm: a connected SessionManagerInterface.
166d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
167d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @raises error.TestFail if policy push failed.
168d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """
1693d68fe8213ef86684d7911f889d56d1345bf3272Chris Masone    listener = session_manager.OwnershipSignalListener(gobject.MainLoop())
1703d68fe8213ef86684d7911f889d56d1345bf3272Chris Masone    listener.listen_for_new_policy()
171d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    sm.StorePolicy(dbus.ByteArray(policy_string), byte_arrays=True)
1723d68fe8213ef86684d7911f889d56d1345bf3272Chris Masone    listener.wait_for_signals(desc='Policy push.')
173d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
174d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    retrieved_policy = sm.RetrievePolicy(byte_arrays=True)
175d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    if retrieved_policy != policy_string:
176d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone        raise error.TestFail('Policy should not be %s' % retrieved_policy)
177d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
178d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
179d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masonedef get_policy(sm):
180d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """Get a device policy from the session manager over DBus.
181d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
182d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    Provided mainly for symmetry with push_policy_and_verify().
183d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
184d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @param sm: a connected SessionManagerInterface.
185d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone
186d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    @return Serialized PolicyFetchResponse.
187d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    """
188d976e0ed3cb28e532f15826c5071149b8fabeaf8Chris Masone    return sm.RetrievePolicy(byte_arrays=True)
189