Keystone client role for resource enforcement on multiple servers

Change-Id: Idcf59060a9fe68be91a2319349811aaab4755e58
diff --git a/README.rst b/README.rst
index 8e539d3..7dc6475 100644
--- a/README.rst
+++ b/README.rst
@@ -261,8 +261,73 @@
           virtual_host: '/openstack'
           ha_queues: true
 
+
+Keystone client
+---------------
+
+Service endpoints enforcement with service token
+
+.. code-block:: yaml
+
+    keystone:
+      client:
+        enabled: true
+        server:
+          keystone01:
+            admin:
+              host: 10.0.0.2
+              port: 35357
+              token: 'service_token'
+            service:
+              nova:
+                type: compute
+                description: OpenStack Compute Service
+                endpoints:
+                - region: region01
+                  public_address: 172.16.10.1
+                  public_port: 8773
+                  public_path: '/v2'
+                  internal_address: 172.16.10.1
+                  internal_port: 8773
+                  internal_path: '/v2'
+                  admin_address: 172.16.10.1
+                  admin_port: 8773
+                  admin_path: '/v2'
+
+Project, users, roles enforcement with admin user
+
+.. code-block:: yaml
+
+    keystone:
+      client:
+        enabled: true
+        server:
+          keystone01:
+            admin:
+              host: 10.0.0.2
+              port: 5000
+              project: 'token'
+              user: admin
+              password: 'passwd'
+            roles:
+            - admin
+            - member
+            project:
+              tenant01:
+                description: "test env"
+                user:
+                  user01:
+                    email: jdoe@domain.com
+                    is_admin: true
+                    password: some
+                  user02:
+                    email: jdoe2@domain.com
+                    password: some
+                    roles:
+                    - custom-roles
+
 Documentation and Bugs
-============================
+======================
 
 To learn how to deploy OpenStack Salt, consult the documentation available
 online at:
diff --git a/keystone/client/init.sls b/keystone/client/init.sls
new file mode 100644
index 0000000..4a3f11d
--- /dev/null
+++ b/keystone/client/init.sls
@@ -0,0 +1,5 @@
+
+include:
+- keystone.client.service
+- keystone.client.project
+- keystone.client.server
diff --git a/keystone/client.sls b/keystone/client/project.sls
similarity index 95%
rename from keystone/client.sls
rename to keystone/client/project.sls
index 151bf55..bb0d30e 100644
--- a/keystone/client.sls
+++ b/keystone/client/project.sls
@@ -1,9 +1,7 @@
 {%- from "keystone/map.jinja" import client with context %}
 {%- if client.enabled %}
 
-keystone_client_packages:
-  pkg.installed:
-  - names: {{ client.pkgs }}
+{%- if client.tenant is defined %}
 
 keystone_salt_config:
   file.managed:
@@ -12,8 +10,6 @@
     - source: salt://keystone/files/salt-minion.conf
     - mode: 600
 
-{%- if client.tenant is defined %}
-
 keystone_client_roles:
   keystone.role_present:
   - names: {{ client.roles }}
diff --git a/keystone/client/server.sls b/keystone/client/server.sls
new file mode 100644
index 0000000..c7c137f
--- /dev/null
+++ b/keystone/client/server.sls
@@ -0,0 +1,140 @@
+{%- from "keystone/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+{%- for server_name, server in client.get('server', {}).iteritems() %}
+
+{%- if server.admin.get('api_version', '2') == '3' %}
+{%- set version = "v3" %}
+{%- else %}
+{%- set version = "v2.0" %}
+{%- endif %}
+
+{%- if server.admin.get('protocol', 'http') == 'http' %}
+{%- set protocol = 'http' %}
+{%- else %}
+{%- set protocol = 'https' %}
+{%- endif %}
+
+
+{%- if server.admin.token is defined %}
+{%- set connection_args = {'endpoint': protocol+'://'+server.admin.host+':'+server.admin.port|string+'/'+version,
+                           'token': server.admin.token} %}
+{%- else %}
+{%- set connection_args = {'auth_url': protocol+'://'+server.admin.host+':'+server.admin.port|string+'/'+version,
+                           'tenant': server.admin.project,
+                           'user': server.admin.user,
+                           'password': server.admin.password} %}
+{%- endif %}
+
+keystone_{{ server_name }}_roles:
+  keystone.role_present:
+  - names: {{ server.roles }}
+  {%- if server.admin.token is defined %}
+  - connection_token: {{ connection_args.token }} 
+  - connection_endpoint: {{ connection_args.endpoint }}
+  {%- else %}
+  - connection_user: {{ connection_args.user }}
+  - connection_password: {{ connection_args.password }}
+  - connection_tenant: {{ connection_args.tenant }}
+  - connection_auth_url: {{ connection_args.auth_url }}
+  {%- endif %}
+
+{% for service_name, service in server.get('service', {}).iteritems() %}
+
+keystone_{{ server_name }}_service_{{ service_name }}:
+  keystone.service_present:
+  - name: {{ service_name }}
+  - service_type: {{ service.type }}
+  - description: {{ service.description }}
+  {%- if server.admin.token is defined %}
+  - connection_token: {{ connection_args.token }} 
+  - connection_endpoint: {{ connection_args.endpoint }}
+  {%- else %}
+  - connection_user: {{ connection_args.user }}
+  - connection_password: {{ connection_args.password }}
+  - connection_tenant: {{ connection_args.tenant }}
+  - connection_auth_url: {{ connection_args.auth_url }}
+  {%- endif %}
+
+{%- for endpoint in service.get('endpoints', ()) %}
+
+keystone_{{ server_name }}_service_{{ service_name }}_endpoint_{{ endpoint.region }}:
+  keystone.endpoint_present:
+  - name: {{ service_name }}
+  - publicurl: '{{ endpoint.get('public_protocol', 'http') }}://{{ endpoint.public_address }}:{{ endpoint.public_port }}{{ endpoint.public_path }}'
+  - internalurl: '{{ endpoint.get('internal_protocol', 'http') }}://{{ endpoint.internal_address }}:{{ endpoint.internal_port }}{{ endpoint.internal_path }}'
+  - adminurl: '{{ endpoint.get('admin_protocol', 'http') }}://{{ endpoint.admin_address }}:{{ endpoint.admin_port }}{{ endpoint.admin_path }}'
+  - region: {{ endpoint.region }}
+  - require:
+    - keystone: keystone_{{ server_name }}_service_{{ service_name }}
+  {%- if server.admin.token is defined %}
+  - connection_token: {{ connection_args.token }} 
+  - connection_endpoint: {{ connection_args.endpoint }}
+  {%- else %}
+  - connection_user: {{ connection_args.user }}
+  - connection_password: {{ connection_args.password }}
+  - connection_tenant: {{ connection_args.tenant }}
+  - connection_auth_url: {{ connection_args.auth_url }}
+  {%- endif %}
+
+{%- endfor %}
+
+{%- endfor %}
+
+{%- for tenant_name, tenant in server.get('project', {}).iteritems() %}
+
+keystone_{{ server_name }}_tenant_{{ tenant_name }}:
+  keystone.tenant_present:
+  - name: {{ tenant_name }}
+  {%- if tenant.description is defined %}
+  - description: {{ tenant.description }} 
+  {%- endif %}
+  {%- if server.admin.token is defined %}
+  - connection_token: {{ connection_args.token }} 
+  - connection_endpoint: {{ connection_args.endpoint }}
+  {%- else %}
+  - connection_user: {{ connection_args.user }}
+  - connection_password: {{ connection_args.password }}
+  - connection_tenant: {{ connection_args.tenant }}
+  - connection_auth_url: {{ connection_args.auth_url }}
+  {%- endif %}
+
+{%- for user_name, user in tenant.get('user', {}).iteritems() %}
+
+keystone_{{ server_name }}_tenant_{{ tenant_name }}_user_{{ user_name }}:
+  keystone.user_present:
+  - name: {{ user_name }}
+  - password: {{ user.password }}
+  {%- if user.email is defined %}
+  - email: {{ user.email }}
+  {%- endif %}
+  - tenant: {{ tenant_name }}
+  - roles:
+      "{{ tenant_name }}":
+        {%- if user.get('is_admin', False) %}
+        - admin
+        {%- elif user.get('roles', False) %}
+        {{ user.roles }}
+        {%- else %}
+        - Member
+        {%- endif %}
+  - require:
+    - keystone: keystone_{{ server_name }}_tenant_{{ tenant_name }}
+    - keystone: keystone_{{ server_name }}_roles
+  {%- if server.admin.token is defined %}
+  - connection_token: {{ connection_args.token }} 
+  - connection_endpoint: {{ connection_args.endpoint }}
+  {%- else %}
+  - connection_user: {{ connection_args.user }}
+  - connection_password: {{ connection_args.password }}
+  - connection_tenant: {{ connection_args.tenant }}
+  - connection_auth_url: {{ connection_args.auth_url }}
+  {%- endif %}
+
+{%- endfor %}
+
+{%- endfor %}
+
+{%- endfor %}
+
+{%- endif %}
diff --git a/keystone/client/service.sls b/keystone/client/service.sls
new file mode 100644
index 0000000..40c68df
--- /dev/null
+++ b/keystone/client/service.sls
@@ -0,0 +1,8 @@
+{%- from "keystone/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+keystone_client_packages:
+  pkg.installed:
+  - names: {{ client.pkgs }}
+
+{%- endif %}