This commit is contained in:
Louis Abel 2023-03-01 19:10:11 -07:00
commit 36dc3a0ec0
Signed by: label
GPG Key ID: 6735C0E1BD65D048
17 changed files with 559 additions and 0 deletions

6
.ansible-lint Normal file
View File

@ -0,0 +1,6 @@
# .ansible-lint
warn_list:
- '204' # Lines should be less than 160 characters
- 'meta-no-info'
skip_list:
- 'role-name'

35
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,35 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
- id: check-case-conflict
- id: check-executables-have-shebangs
- id: check-json
- id: pretty-format-json
- id: detect-private-key
- repo: local
hooks:
- id: ansible-lint
name: Ansible-lint
description: This hook runs ansible-lint.
entry: ansible-lint -v --force-color
language: python
# do not pass files to ansible-lint, see:
# https://github.com/ansible/ansible-lint/issues/611
pass_filenames: false
always_run: true
additional_dependencies:
- ansible-core>=2.13.3
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.29.0
hooks:
- id: yamllint
files: \.(yaml|yml)$
types: [file, yaml]
entry: yamllint

11
.yamllint Normal file
View File

@ -0,0 +1,11 @@
---
extends: default
rules:
line-length:
max: 140
level: warning
ignore: |
.travis.yml
.github

18
CHANGELOG.md Normal file
View File

@ -0,0 +1,18 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
- what do we need to do
## [0.0.1] - 2020-12-13
### Added
- Initial
### Changed
- None
### Removed
- None

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Louis Abel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# Ansible template role: Ipsilon
Role that fulfills some need (ipsilon )and there was not some sort of equivalent elsewhere.

53
defaults/main.yml Normal file
View File

@ -0,0 +1,53 @@
---
# Defaults variables for role ipsilon
ipsilon_db_user: ipsilon
ipsilon_db_password: ThisIsNotThePassword
ipsilon_db_host: dbhost
ipsilon_db_name: ipsilon_db
idp_hostname: accounts.rockylinux.org
# The list of ipsilon packages
ipsilon_packages:
- ipsilon
- ipsilon-authform
- ipsilon-base
- ipsilon-filesystem
- ipsilon-infofas
- ipsilon-infosssd
- ipsilon-openid
- ipsilon-openidc
- ipsilon-saml2
- ipsilon-saml2-base
- ipsilon-tools-ipa
- python3-setuptools
- python3-freeipa
- httpd
- mod_ssl
- mod_auth_openidc
- mod_auth_gssapi
- git
ipsilon_booleans:
- httpd_can_network_connect
- httpd_can_network_connect_db
- httpd_dbus_sssd
- httpd_tmp_exec
- httpd_mod_auth_patm
ipsilon_openid_trusted_roots:
- https://git.rockylinux.org/
- https://vote.rockylinux.org/
- https://lists.resf.org/
ipsilon_openidc_scopes:
- ipsilon
- rocky
ipsilon_openidc_custom_scopes:
- rocky
ipsilon_fas_username: userman
ipsilon_fas_password: ThisIsNotThePassword
ipsilon_oidc_salt: data
ipsilon_saml2_salt: data
...

97
files/generate-oidc-token Normal file
View File

@ -0,0 +1,97 @@
#!/usr/bin/python3
# Copyright (c) 2018 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
This script will accept some parameters and will print out some SQL you can run against the Ipsilon
database, and a token you can give to an application to authenticate against a service.
"""
import base64
import json
import os
import time
import uuid
import click
secret = base64.urlsafe_b64encode(os.urandom(64))[:64].decode()
template = """
Run this SQL against Ipsilon's database:
--------START CUTTING HERE--------
BEGIN;
insert into token values ('{uuid}','username','{service_name}@service');
insert into token values ('{uuid}','security_check','{secret}');
insert into token values ('{uuid}','client_id','{service_name}');
insert into token values ('{uuid}','expires_at','{expiration}');
insert into token values ('{uuid}','type','Bearer');
insert into token values ('{uuid}','issued_at','{now}');
insert into token values ('{uuid}','scope','{scope}');
COMMIT;
-------- END CUTTING HERE --------
"""
def validate_scopes(ctx, param, scopes):
"""
Ensure that the user provided at least one scope.
Args:
ctx(click.core.Context): Unused.
param (click.core.Option): Unused.
scopes (tuple): The scopes provided by the user that we are validating.
Raises:
click.BadParameter: If the length of the scopes tuple is less than 1.
"""
if len(scopes) < 1:
raise click.BadParameter('At least one scope must be provided.')
return scopes
@click.command()
@click.argument('service_name')
@click.option('--expiration', '-e', prompt='Number of days until expiration', type=int,
help='The number of days from now until this token expires.')
@click.option('--scope', '-s', multiple=True, callback=validate_scopes,
help='A scope to include for this token. May be supplied multiple times.')
@click.option('--no-openid', is_flag=True, help='Do not use "openid" as the first item in scope.')
def generate_token(service_name, expiration, scope, no_openid):
"""
Print out SQL to insert a token in the Ipsilon database, and the token itself.
SERVICE_NAME is the name of the service that the token will be used by, (e.g., bodhi).
"""
identifier = uuid.uuid4()
now = int(time.time())
expiration = now + (expiration * 24 * 3600)
scope = list(scope)
if not no_openid:
scope.insert(0, 'openid')
scope = json.dumps(scope)
print(template.format(uuid=identifier, service_name=service_name, secret=secret,
expiration=expiration, scope=scope, now=now))
print("Token: {}_{}\n".format(identifier, secret))
if __name__ == '__main__':
generate_token()

18
files/genkey.py Normal file
View File

@ -0,0 +1,18 @@
#!/usr/bin/python3
import time
import os.path
from jwcrypto.jwk import JWK, JWKSet
keyid = int(time.time())
keyset = JWKSet()
rsasig = JWK(generate='RSA', size=2048, use='sig',
kid='%s-sig' % keyid)
keyset.add(rsasig)
rsasig = JWK(generate='RSA', size=2048, use='enc',
kid='%s-enc' % keyid)
keyset.add(rsasig)
with open('/etc/ipsilon/openidc.key', 'w') as m:
m.write(keyset.export())

31
files/rocky.py Normal file
View File

@ -0,0 +1,31 @@
from __future__ import absolute_import
from ipsilon.providers.openidc.plugins.common import OpenidCExtensionBase
class OpenidCExtension(OpenidCExtensionBase):
name = 'rocky'
display_name = 'Rocky Tokens'
scopes = {
'openid': {
'display_name': 'openid',
},
'profile': {
'display_name': 'profile',
},
'email': {
'display_name': 'email',
},
'address': {
'display_name': 'address',
},
'phone': {
'display_name': 'phone',
},
'https://mbs.rockylinux.org/oidc/mbs-submit-build': {
'display_name': 'mbs',
},
'https://id.fedoraproject.org/scope/groups': {
'display_name': 'groups',
}
}

BIN
files/rocky_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

11
handlers/main.yml Normal file
View File

@ -0,0 +1,11 @@
---
# Defaults handlers for role ipsilon
- name: restart_sssd
ansible.builtin.service:
name: sssd
state: restarted
- name: reload_httpd
ansible.builtin.service:
name: httpd
state: reloaded

53
meta/main.yml Normal file
View File

@ -0,0 +1,53 @@
galaxy_info:
author: your name
description: your role description
company: your company (optional)
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: MIT
min_ansible_version: 2.8
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
#
# Provide a list of supported platforms, and for each platform a list of versions.
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
# To view available platforms and versions (or releases), visit:
# https://galaxy.ansible.com/api/v1/platforms/
#
# platforms:
# - name: Fedora
# versions:
# - all
# - 25
# - name: SomePlatform
# versions:
# - all
# - 1.0
# - 7
# - 99.99
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.

102
tasks/main.yml Normal file
View File

@ -0,0 +1,102 @@
---
- name: Install required packages
ansible.builtin.dnf:
name: "{{ ipsilon_packages }}"
state: installed
tags:
- packages
- name: Initialize ipsilon if needed
ansible.builtin.command: >
ipsilon-server-install
--secure yes
--openid yes
--openidc yes
--saml2 yes
--ipa yes
--info-sssd yes
--form yes
--gssapi-httpd-keytab /etc/httpd.keytab
--admin-user admin
--hostname {{ idp_hostname }}
args:
creates: /etc/ipsilon/idp/ipsilon.conf
no_log: true
register: ipsilon_install
tags:
- init
- name: Set booleans
ansible.posix.seboolean:
name: "{{ item }}"
state: true
persistent: true
loop: "{{ ipsilon_booleans }}"
tags:
- selinux
- name: Branding ipsilon with logo
ansible.builtin.copy:
src: rocky_logo.png
dest: "{{ item }}"
owner: root
group: root
mode: '0644'
with_items:
- /usr/share/ipsilon/ui/img/brand-lg.png
- /usr/share/ipsilon/ui/img/brand.png
- name: Distributing openidc genkey script
ansible.builtin.copy:
src: genkey.py
dest: /var/lib/ipsilon/idp/genkey.py
mode: '0755'
owner: ipsilon
group: ipsilon
- name: Generate oidc token script
ansible.builtin.copy:
src: generate-oidc-token
dest: /var/lib/ipsilon/idp/generate-oidc-token
mode: '0755'
owner: ipsilon
group: ipsilon
- name: Distribute ipsilon.conf
ansible.builtin.template:
src: "ipsilon.conf"
dest: /etc/ipsilon/idp/ipsilon.conf
owner: ipsilon
group: ipsilon
mode: 0600
tags:
- config
notify:
- restart_httpd
- name: Distribute configuration.conf
ansible.builtin.template:
src: "configuration.conf"
dest: /etc/ipsilon/idp/configuration.conf
owner: ipsilon
group: ipsilon
mode: 0600
tags:
- config
notify:
- restart_httpd
- name: Configure SSSD part 1
ansible.builtin.replace:
path: /etc/sssd/sssd.conf
regexp: ^ldap_user_extra_attrs = [\w,\s]+$
replace: ldap_user_extra_attrs = mail, street, locality, st, postalCode, telephoneNumber, givenname, sn, fasTimeZone, fasLocale, fasIRCNick, fasGPGKeyId, fasCreationTime, fasStatusNote, fasRHBZEmail, fasGitHubUsername, fasGitLabUsername, fasWebsiteURL, fasIsPrivate, ipaSshPubKey
notify: restart_sssd
- name: Configure SSSD part 2
ansible.builtin.replace:
path: /etc/sssd/sssd.conf
regexp: ^user_attributes = [\w,\s]+$
replace: user_attributes = +mail, +street, +locality, +st, +postalCode, +telephoneNumber, +givenname, +sn, +fasTimeZone, +fasLocale, +fasIRCNick, +fasGPGKeyId, +fasCreationTime, +fasStatusNote, +fasRHBZEmail, +fasGitHubUsername, +fasGitLabUsername, +fasWebsiteURL, +fasIsPrivate, +ipaSshPubKey
notify: restart_sssd
...

View File

@ -0,0 +1,74 @@
[info_config]
sssd preconfigured = True
global enabled = sssd,nss,fas
fas fas url = https://accounts.rockylinux.org/
fas fas proxy client user agent = Ipsilon v1.0
fas fas insecure auth = False
fas bind username = {{ ipsilon_fas_username }}
fas bind password = {{ ipsilon_fas_password }}
fas preconfigured=True
[sssd_data]
[nss_data]
[fas_data]
[login_config]
fas fas url = https://accounts.rockylinux.org
fas fas proxy client user agent = Ipsilon v1.0
fas fas insecure auth = False
fas username text = RAS Username
fas password text = Password
fas help text = Login with your RAS credentials
global enabled = gssapi,form
[gssapi_data]
[form_data]
[provider_config]
openidc database url = postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}
openidc static database url = postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}
openidc enabled extensions = ipsilon, mbs, fedora-account
openidc endpoint url = https://{{ idp_hostname }}/idp/openidc/
openidc documentation url = https://ipsilonproject.org/doc/openidc/
openidc policy url = http://www.example.com/
openidc tos url = http://www.example.com/
openidc idp key file = /var/lib/ipsilon/idp/openidc/openidc.key
openidc idp sig key id = 1633884828-sig
openidc idp subject salt = {{ ipsilon_oidc_salt }}
openidc allow dynamic client registration = True
openidc default attribute mapping = [["*", "*"], ["_groups", "groups"], [["_extras", "cla"], "cla"], ["fullname", "name"], ["_username", "nickname"], ["_username", "preferred_username"], ["fasIRCNick", "ircnick"], ["fasLocale", "locale"], ["fasTimeZone", "zoneinfo"], ["fasTimeZone", "timezone"], ["fasWebsiteURL", "website"], ["fasGPGKeyId", "gpg_keyid"], ["ipaSshPubKey", "ssh_key"], ["fasIsPrivate", "privacy"], ["fullname", "human_name"]]
openidc default allowed attributes = ["*"]
openidc access token lifetime = 3600
openidc refresh token lifetime = 31536000
global enabled = openidc,saml2,openid
openid default allowed attributes = ["*"]
openid database url = postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}
openid default email domain =
openid endpoint url = https://{{ idp_hostname }}/idp/openid/
openid identity url template = https://{{ idp_hostname }}/idp/openid/id/%(username)s
openid trusted roots = {{ ipsilon_openid_trust_roots }}
openid untrusted roots =
openid enabled extensions = Attribute Exchange, CLAs, Fedora Teams, Simple Registration, Teams, API
openid default attribute mapping = [["*", "*"], ["_groups", "groups"], [["_extras", "cla"], "cla"], ["fullname", "name"], ["_username", "nickname"], ["_username", "preferred_username"], ["fasIRCNick", "ircnick"], ["fasLocale", "locale"], ["fasTimeZone", "zoneinfo"], ["fasTimeZone", "timezone"], ["fasWebsiteURL", "website"], ["fasGPGKeyId", "gpg_keyid"], ["ipaSshPubKey", "ssh_key"], ["fasIsPrivate", "privacy"], ["fullname", "human_name"], ["mail", "email"]]
saml2 idp storage path = /var/lib/ipsilon/idp/saml2
saml2 idp metadata file = metadata.xml
saml2 idp certificate file = /var/lib/ipsilon/idp/saml2/idp.pem
saml2 idp key file = /var/lib/ipsilon/idp/saml2/idp.key
saml2 idp nameid salt = {{ ipsilon_saml2_salt }}
saml2 idp metadata validity = 1825
saml2 session database url = postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}
[openidc_data]
[saml2_data]
[openid_data]
[authz_config]
global enabled = allow
[allow_data]

24
templates/ipsilon.conf Normal file
View File

@ -0,0 +1,24 @@
[global]
debug = True
tools.log_request_response.on = True
template_dir = "templates"
cache_dir = "/var/cache/ipsilon"
cleanup_interval = 30
db.conn.log = False
db.echo = False
base.mount = "/idp"
base.dir = "/usr/share/ipsilon"
#admin.config.db = "configfile:///etc/ipsilon/idp/configuration.conf"
admin.config.db = "postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}"
user.prefs.db = "postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}"
transactions.db = "postgresql://{{ ipsilon_db_user }}:{{ ipsilon_db_password }}@{{ ipsilon_db_host }}/{{ ipsilon_db_name }}"
tools.sessions.on = True
tools.sessions.name = "idp_ipsilon_session_id"
tools.sessions.storage_type = "file"
tools.sessions.storage_path = "/var/lib/ipsilon/idp/sessions"
tools.sessions.path = "/idp"
tools.sessions.timeout = 30
tools.sessions.httponly = True
tools.sessions.secure = True

3
vars/main.yml Normal file
View File

@ -0,0 +1,3 @@
---
# vars file - Nothing should really go here but dynamic imports
# and truely static items