Skip to content

Commit 2ce28de

Browse files
authored
Merge pull request #333 from adobe-apiplatform/v2
prepare for 2.3rc4 release. This fixes #89.
2 parents dd0cec7 + 8436a4d commit 2ce28de

File tree

10 files changed

+354
-89
lines changed

10 files changed

+354
-89
lines changed

README.md

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,57 +58,78 @@ While that looks simple, the `make pex` command will try to download and install
5858
We pre-package releases on Ubuntu, so the advice here is definitely accurate for that platform, but something similar should work for most other Debian variants.
5959

6060
* Make sure you have Python 2.7.5 or above; earlier versions will give you InsecurePlatformWarning messages due to older SSL components.
61+
* For Ubuntu 16.04, an easy way to get python 3.6 is from the Jonathan F archive, do:
62+
```bash
63+
sudo add-apt-repository ppa:jonathonf/python-3.6
64+
sudo apt-get update
65+
sudo pat-get install -y python3.6
66+
```
6167
* Take all security updates before you start.
6268
* You don't need a GUI on the platform, as the entire build can be done from the command line. Server variants are fine.
6369
* You will need a standard C development environment to build a variety of the modules that use native extensions. Use this command to get one:
6470
```bash
65-
sudo apt-get install build-essential
71+
sudo apt-get install -y build-essential
6672
```
6773
* Make sure you use the system package manager to install the following packages (and their dependencies):
68-
* python-dev (or python3-dev if you are doing python3 builds)
69-
* python-pip (not needed for python3)
70-
* python-virtualenv (not needed for python3)
74+
* python-dev (or python3.6-dev if you are doing python3 builds)
75+
* python-pip (or python3-pip if you are doing python3 builds)
76+
* python-virtualenv (or python3-virtualenv if you are doing python3 builds)
7177
* pkg-config
7278
* libssl-dev
7379
* libldap2-dev
7480
* libsasl2-dev
75-
* libdbus-glib-1-dev
81+
* python-dbus-devel
7682
* libffi-dev
77-
* For convenience, you can copy and paste this command:
83+
* For convenience, you can copy and paste these commands (choosing from the first two based on your python version):
7884
```bash
79-
sudo apt-get install python-dev python-pip python-virtualenv pkg-config libssl-dev libldap2-dev libsasl2-dev libdbus-glib-1-dev libffi-dev
85+
sudo apt-get install -y python-dev python-pip python-virtualenv
86+
sudo apt-get install -y python3.6-dev
87+
sudo apt-get install -y pkg-config libssl-dev libldap2-dev libsasl2-dev dbus-glib-devel python-dbus libffi-dev
8088
```
81-
* You don't need the python-dbus package to _build_ user-sync, but you will need it to run user-sync if you use the dbus secure store for your credentials.
89+
* You need the python-dbus package to _build_ user-sync, but you don't need it to *run* user-sync unless you use the dbus secure store for your credentials.
8290

8391
### CentOS and other RedHat variants
8492

8593
We pre-package releases on CentOS, so the advice here is definitely accurate for that platform, but something similar should work for most other RedHat variants.
8694

8795
* Make sure you have Python 2.7.5 or above; earlier versions will give you InsecurePlatformWarning messages due to older SSL components.
96+
* You cannot build on CentOS 6, because user-sync uses python-dbus for the keyring, and python-dbus requires dbus 1.6 or greater which is not available on CentOS 6. However, you can run a CentOS 7 build on CentOS 6 as long as you are running the same build of python 3.6 or later.
97+
* For centos6, to run builds, you will need to install python 3.6, which you can do as follows:
98+
```bash
99+
sudo yum install -y https://centos6.iuscommunity.org/ius-release.rpm # installs inline-upstream-stable pkg repo
100+
sudo yum install -y python36u-devel python36u-pip python36u-virtualenv
101+
```
102+
* For centos7, to install python 3.6, do the following:
103+
```bash
104+
sudo yum install -y https://centos7.iuscommunity.org/ius-release.rpm # installs inline-upstream-stable pkg repo
105+
sudo yum install -y python36u-devel python36u-pip python36u-virtualenv
106+
```
88107
* Take all security updates before you start.
89108
* You don't need a GUI on the platform, as the entire build can be done from the command line. Server variants are fine.
90109
* You will need a standard C development environment to build a variety of the modules that use native extensions. Use this command to get one:
91110
```bash
92-
sudo yum group install "Development Tools"
111+
sudo yum groupinstall -y "Development Tools"
93112
```
94113
* Your OS may not know about `pip` by default, although it will know about `virtualenv`. Rather than installing `pip` manually, we recommend telling your OS about the Red Hat "Extra Package for Enterprise Linux (EPEL)" package library, which on CentOS you can do with:
95114
```bash
96-
sudo yum install epel-release
115+
sudo yum install -y epel-release
97116
```
98117
* Make sure you use the system package manager to install the following packages (and their dependencies):
99-
* python-devel (or python3-devel, if you are doing python3 builds)
100-
* python-pip (not needed for python3)
101-
* python-virtualenv (not needed for python3)
118+
* python-devel (or python36u-devel, if you are doing python3 builds)
119+
* python-pip (or python36u-pip, if you are doing python3 builds)
120+
* python-virtualenv (or python36u-virtualenv, if you are doing python3 builds)
102121
* pkgconfig
103122
* openssl-devel
104123
* openldap-devel (includes sasl)
105124
* dbus-glib-devel
125+
* dbus-python (version 1.6 or greater, not available on CentOS 6)
106126
* libffi-devel
107-
* For convenience, you can copy and paste this command:
127+
* For convenience, you can copy and paste these commands (pick among the first two based on your python version):
108128
```bash
109-
sudo yum install python-devel python-pip python-virtualenv pkgconfig openssl-devel openldap-devel dbus-glib-devel libffi-devel
129+
sudo yum install -y python-devel python-pip python-virtualenv
130+
sudo yum install -y python36u-devel python36u-pip python36u-virtualenv
131+
sudo yum install -y pkgconfig openssl-devel openldap-devel dbus-glib-devel dbus-python libffi-devel
110132
```
111-
* You don't need the python-dbus package to _build_ user-sync, but you will need it to run user-sync if you use the dbus secure store for your credentials.
112133
113134
### Mac OS X
114135

RELEASE_NOTES.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Release Notes for User Sync Tool Version 2.3
22

3-
These notes apply to v2.3rc3 of 2017-12-10.
3+
These notes apply to v2.3rc4 of 2018-01-29.
44

55
## New Features
66

@@ -12,16 +12,26 @@ There is a new command-line argument `--connector` for specifying whether to get
1212

1313
[#299](https://github.com/adobe-apiplatform/user-sync.py/issues/299) You can now use an `invocation_defaults` section to specify desired values for command-line arguments in the main configuration file. This can make it a lot easier to repeat runs with a stable set of arguments, even when running interactively rather than from a script. The sample main configuration file specifies the configuration parameters to use as well as the syntax for specifying values. See [the docs](https://adobe-apiplatform.github.io/user-sync.py/en/user-manual/command_parameters.html) for full details.
1414

15+
[#322](https://github.com/adobe-apiplatform/user-sync.py/issues/322), [#319](https://github.com/adobe-apiplatform/user-sync.py/issues/319) As it has been with email, you can now use formatted combinations of ldap/okta attributes for the Adobe-side first name, last name, and country. (See the sample configuration files for details.) You can also specify the country code in lower case.
16+
1517
## Bug Fixes
1618

1719
[#305](https://github.com/adobe-apiplatform/user-sync.py/issues/305) General issues with Okta connector.
1820

1921
[#306](https://github.com/adobe-apiplatform/user-sync.py/issues/306) v2.2.2 crashes if country code not specified.
2022

23+
[#308](https://github.com/adobe-apiplatform/user-sync.py/issues/308) docs are unclear about how to set PEX_ROOT.
24+
2125
[#314](https://github.com/adobe-apiplatform/user-sync.py/issues/314) invocation_defaults section should be optional.
2226

2327
[#315](https://github.com/adobe-apiplatform/user-sync.py/issues/315) Can't specify --user-filter or other string-valued args.
2428

29+
[#318](https://github.com/adobe-apiplatform/user-sync.py/issues/318) Fix the README build instructions regarding dbus.
30+
31+
[#324](https://github.com/adobe-apiplatform/user-sync.py/issues/324) Handle LDAP servers with no support for PagedResults.
32+
33+
[#325](https://github.com/adobe-apiplatform/user-sync.py/issues/325) Adding '--process-groups' doesn't override the default.
34+
2535
## Compatibility with Prior Versions
2636

2737
All configuration and command-line arguments accepted in prior releases work in this release. The `--users file` argument is still accepted, and is equivalent to (although more limited than) specifying `--connector csv`.

examples/config files - basic/3 connector-ldap.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,36 @@ user_email_format: "{mail}"
133133
# produce a unique username for each user.
134134
#user_username_format: "{department}_{user_id}"
135135

136+
# (optional) user_given_name_format (default value given below)
137+
# user_given_name_format specifies how to construct a user's given name by
138+
# combining constant strings with the values of specific directory attributes.
139+
# Any names in curly braces are taken as attribute names, and everything including
140+
# the braces will be replaced on a per-user basis with the values of the attributes.
141+
# The default value used here is simple, and suitable for OpenLDAP systems.
142+
# NOTE: for this and every format setting, the constant strings must be in
143+
# the encoding specified by the string_encoding setting, above.
144+
#user_given_name_format: "{givenName}"
145+
146+
# (optional) user_surname_format (default value given below)
147+
# user_surname_format specifies how to construct a user's surname by
148+
# combining constant strings with the values of specific directory attributes.
149+
# Any names in curly braces are taken as attribute names, and everything including
150+
# the braces will be replaced on a per-user basis with the values of the attributes.
151+
# The default value used here is simple, and suitable for OpenLDAP systems.
152+
# NOTE: for this and every format setting, the constant strings must be in
153+
# the encoding specified by the string_encoding setting, above.
154+
#user_surname_format: "{sn}"
155+
156+
# (optional) user_country_code_format (default value given below)
157+
# user_country_code_format specifies how to construct a user's country code by
158+
# combining constant strings with the values of specific directory attributes.
159+
# Any names in curly braces are taken as attribute names, and everything including
160+
# the braces will be replaced on a per-user basis with the values of the attributes.
161+
# The default value used here is simple, and suitable for OpenLDAP systems.
162+
# NOTE: for this and every format setting, the constant strings must be in
163+
# the encoding specified by the string_encoding setting, above.
164+
#user_country_code_format: "{c}"
165+
136166
# Some additional info about LDAP connectors:
137167
#
138168
# Unlike the CSV connector, the LDAP connector does not have custom specifications

examples/config files - basic/5 connector-okta.yml

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,83 @@ all_users_filter: 'user.status == "ACTIVE"'
3434
# the valid values are: enterpriseID, federatedID
3535
# If not specified, the default identity type from the main config file is used.
3636
# user_identity_type: federatedID
37+
38+
# (optional) string_encoding (default value given below)
39+
# string_encoding specifies the Unicode string encoding used by the directory.
40+
# All values retrieved from the directory are converted to Unicode before being
41+
# sent to or compared with values on the Adobe side, to avoid encoding issues.
42+
# The value must be a Python codec name or alias, such as 'latin1' or 'big5'.
43+
# See https://docs.python.org/2/library/codecs.html#standard-encodings for details.
44+
#string_encoding: utf8
45+
46+
# (optional) user_identity_type_format (no default)
47+
# user_identity_type_format specifies how to construct a user's desired identity
48+
# type on the Adobe side by combining constant strings with attribute values.
49+
# Any names in curly braces are take as attribute names, and everything including
50+
# the braces will be replaced on a per-user basis with the values of the attributes.
51+
# There is no default value for this setting, because most directories don't contain
52+
# users with different identity types (so setting the default identity type suffices).
53+
# If your directory contains users of different identity types, you should define
54+
# this field to look at the value of an appropriate attribute in your okta user profile.
55+
# For example, if your Okta user profile attribute "idType" had one of the values
56+
# adobe, enterprise, or federated in it for each user, you could use:
57+
#user_identity_type_format: "{idType}ID"
58+
59+
# (optional) user_email_format (default value given below)
60+
# user_email_format specifies how to construct a user's email address by
61+
# combining constant strings with the values of specific Okta profile attributes.
62+
# Any names in curly braces are taken as attribute names, and everything including
63+
# the braces will be replaced on a per-user basis with the values of the attributes.
64+
# The default value is from "email" field in Okta user profile.
65+
# NOTE: for this and every format setting, the constant strings must be in
66+
# the encoding specified by the string_encoding setting, above.
67+
user_email_format: "{email}"
68+
69+
# (optional) user_domain_format (no default value)
70+
# user_domain_format is analogous to user_email_format in syntax, but it
71+
# is used to discover the domain for a given user. If not specified, the
72+
# domain is taken from the domain part of the user's email address.
73+
#user_domain_format: "{domain}"
74+
75+
# (optional) user_username_format (no default value)
76+
# user_username_format specifies how to construct a user's username on the
77+
# Adobe side by combining constant strings with attribute values.
78+
# Any names in curly braces are taken as attribute names, and everything including
79+
# the braces will be replaced on a per-user basis with the values of the attributes.
80+
# This setting should only be used when you are using federatedID and your
81+
# federation configuration specifies username-based login. In all other cases,
82+
# make sure this is not set or returns an empty value, and the user's username
83+
# will be taken from the user's email.
84+
# This example supposes that the department and user_id are concatenated to
85+
# produce a unique username for each user.
86+
#user_username_format: "{department}_{user_id}"
87+
88+
# (optional) user_given_name_format (default value given below)
89+
# user_given_name_format specifies how to construct a user's given name by
90+
# combining constant strings with the values of specific Okta profile attributes.
91+
# Any names in curly braces are taken as attribute names, and everything including
92+
# the braces will be replaced on a per-user basis with the values of the attributes.
93+
# The default value is from "firstName" field in Okta user profile..
94+
# NOTE: for this and every format setting, the constant strings must be in
95+
# the encoding specified by the string_encoding setting, above.
96+
#user_given_name_format: "{firstName}"
97+
98+
# (optional) user_surname_format (default value given below)
99+
# user_surname_format specifies how to construct a user's surname by
100+
# combining constant strings with the values of specific Okta profile attributes.
101+
# Any names in curly braces are taken as attribute names, and everything including
102+
# the braces will be replaced on a per-user basis with the values of the attributes.
103+
# The default value is from "lastName" field in Okta user profile.
104+
# NOTE: for this and every format setting, the constant strings must be in
105+
# the encoding specified by the string_encoding setting, above.
106+
#user_surname_format: "{lastName}"
107+
108+
# (optional) user_country_code_format (default value given below)
109+
# user_country_code_format specifies how to construct a user's country code by
110+
# combining constant strings with the values of specific Okta profile attributes.
111+
# Any names in curly braces are taken as attribute names, and everything including
112+
# the braces will be replaced on a per-user basis with the values of the attributes.
113+
# The default value is from "countryCode" field in Okta user profile.
114+
# NOTE: for this and every format setting, the constant strings must be in
115+
# the encoding specified by the string_encoding setting, above.
116+
#user_country_code_format: "{countryCode}"

tests/connector/directory_okta_test.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,17 +250,12 @@ def __init__(self, status_code, data):
250250
self.links = {}
251251

252252
self.mock_response = MockResponse
253-
self.orig_directory_init = OktaDirectoryConnector.__init__
254-
OktaDirectoryConnector.__init__ = mock.Mock(return_value=None)
255-
directory = OktaDirectoryConnector({})
253+
directory = OktaDirectoryConnector({'host': 'okta-test.com', 'api_token': 'abcdefghijklmnopqrstuvwxyz'})
256254
directory.logger = mock.create_autospec(logging.Logger)
257255
directory.groups_client = okta.UserGroupsClient('example.com', 'xyz')
258256
directory.user_identity_type = 'enterpriseID'
259257
self.directory = directory
260258

261-
def tearDown(self):
262-
OktaDirectoryConnector.__init__ = self.orig_directory_init
263-
264259
@mock.patch('user_sync.connector.directory_okta.OktaDirectoryConnector.find_group')
265260
@mock.patch('okta.framework.ApiClient.requests')
266261
def test_success_extended_attribute_key(self, mock_requests, mock_find_group):
@@ -281,7 +276,6 @@ def test_success_extended_attribute_key(self, mock_requests, mock_find_group):
281276
mock_find_group.return_value = mockID
282277

283278
directory = self.directory
284-
directory.options = {'all_users_filter': 'user.status == "ACTIVE"', 'group_filter_format': '{group}'}
285279
extended_attributes = ['firstName', 'lastName', 'login', 'email', 'countryCode', 'additionalTest']
286280
iterGroupResponse = directory.iter_group_members("testGroup",directory.options['all_users_filter'], extended_attributes)
287281
temp_var = list(iterGroupResponse)
@@ -308,7 +302,6 @@ def test_success_extended_attribute_value(self, mock_requests, mock_find_group):
308302
mock_find_group.return_value = mockID
309303

310304
directory = self.directory
311-
directory.options = {'all_users_filter': 'user.status == "ACTIVE"', 'group_filter_format': '{group}'}
312305
extended_attributes = ['firstName', 'lastName', 'login', 'email', 'countryCode', 'additionalTest']
313306
iterGroupResponse = directory.iter_group_members("testGroup", directory.options['all_users_filter'],
314307
extended_attributes)
@@ -336,7 +329,6 @@ def test_non_existence_extended_attribute_key(self, mock_requests, mock_find_gro
336329
mock_find_group.return_value = mockID
337330

338331
directory = self.directory
339-
directory.options = {'all_users_filter': 'user.status == "ACTIVE"', 'group_filter_format': '{group}'}
340332
extended_attributes = ['firstName', 'lastName', 'login', 'email', 'countryCode', 'badattribute']
341333
iterGroupResponse = directory.iter_group_members("testGroup", directory.options['all_users_filter'],
342334
extended_attributes)
@@ -364,7 +356,6 @@ def test_non_existence_extended_attribute_value(self, mock_requests, mock_find_g
364356
mock_find_group.return_value = mockID
365357

366358
directory = self.directory
367-
directory.options = {'all_users_filter': 'user.status == "ACTIVE"', 'group_filter_format': '{group}'}
368359
extended_attributes = ['firstName', 'lastName', 'login', 'email', 'countryCode', 'badattribute']
369360
iterGroupResponse = directory.iter_group_members("testGroup", directory.options['all_users_filter'],
370361
extended_attributes)
@@ -391,7 +382,6 @@ def test_invalid_missing_profile_user(self, mock_requests, mock_find_group):
391382
mock_find_group.return_value = mockID
392383

393384
directory = self.directory
394-
directory.options = {'all_users_filter': 'user.status == "ACTIVE"', 'group_filter_format': '{group}'}
395385
extended_attributes = ['firstName', 'lastName', 'login', 'email', 'countryCode', 'badattribute']
396386
iterGroupResponse = directory.iter_group_members("testGroup", directory.options['all_users_filter'],
397387
extended_attributes)

0 commit comments

Comments
 (0)