From 08cd2799ce5fcc6244c917f8f31c5932c996ee71 Mon Sep 17 00:00:00 2001 From: Markus Pesch Date: Mon, 28 Apr 2025 11:28:52 +0200 Subject: [PATCH] Initial COmmit --- .ansible-lint | 4 + .editorconfig | 12 +++ .gitea/workflows/ansible-linters.yaml | 20 ++++ .gitea/workflows/markdown-linters.yaml | 19 ++++ .gitignore | 1 + .markdownlint.yaml | 137 +++++++++++++++++++++++++ .vscode/settings.json | 14 +++ .yamllint.yaml | 17 +++ LICENSE | 20 ++++ README.md | 24 +++++ default/main.yml | 12 +++ meta/main.yml | 23 +++++ renovate.json | 9 ++ tasks/main.yml | 115 +++++++++++++++++++++ templates/root/.ssh/authorized_keys.j2 | 10 ++ templates/root/.ssh/config.j2 | 15 +++ 16 files changed, 452 insertions(+) create mode 100644 .ansible-lint create mode 100644 .editorconfig create mode 100644 .gitea/workflows/ansible-linters.yaml create mode 100644 .gitea/workflows/markdown-linters.yaml create mode 100644 .gitignore create mode 100644 .markdownlint.yaml create mode 100644 .vscode/settings.json create mode 100644 .yamllint.yaml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 default/main.yml create mode 100644 meta/main.yml create mode 100644 renovate.json create mode 100644 tasks/main.yml create mode 100644 templates/root/.ssh/authorized_keys.j2 create mode 100644 templates/root/.ssh/config.j2 diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..23a163f --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,4 @@ +--- + +exclude_paths: +- .gitea/ diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..ad4c311 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = false diff --git a/.gitea/workflows/ansible-linters.yaml b/.gitea/workflows/ansible-linters.yaml new file mode 100644 index 0000000..09dfc7c --- /dev/null +++ b/.gitea/workflows/ansible-linters.yaml @@ -0,0 +1,20 @@ +name: Ansible Linter + +on: + pull_request: + types: [ "opened", "reopened", "synchronize" ] + push: + branches: [ '**' ] + tags-ignore: [ '**' ] + +jobs: + ansible-lint: + runs-on: + - ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run ansible-lint + uses: ansible/ansible-lint@v25.2.1 + with: + args: "--config-file .ansible-lint" + setup_python: "true" diff --git a/.gitea/workflows/markdown-linters.yaml b/.gitea/workflows/markdown-linters.yaml new file mode 100644 index 0000000..4ec7a3a --- /dev/null +++ b/.gitea/workflows/markdown-linters.yaml @@ -0,0 +1,19 @@ +name: Lint Markdown files + +on: + pull_request: + types: [ "opened", "reopened", "synchronize" ] + push: + branches: [ '**' ] + tags-ignore: [ '**' ] + +jobs: + markdown-lint: + container: + image: git.cryptic.systems/volker.raschek/markdownlint:0.44.0 + runs-on: + - ubuntu-latest + steps: + - uses: actions/checkout@v4.2.2 + - name: Lint Markdown files + run: markdownlint --config .markdownlint.yaml . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..feaf22e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.ansible \ No newline at end of file diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..0cca4db --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,137 @@ +# markdownlint YAML configuration +# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD003/heading-style/header-style - Heading style +MD003: + # Heading style + style: "atx" + +# MD004/ul-style - Unordered list style +MD004: + style: "dash" + +# MD007/ul-indent - Unordered list indentation +MD007: + # Spaces for indent + indent: 2 + # Whether to indent the first level of the list + start_indented: false + +# MD009/no-trailing-spaces - Trailing spaces +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs - Hard tabs +MD010: + # Include code blocks + code_blocks: true + +# MD012/no-multiple-blanks - Multiple consecutive blank lines +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 120 + # Number of characters for headings + heading_line_length: 120 + # Number of characters for code blocks + code_block_line_length: 120 + # Include code blocks + code_blocks: false + # Include tables + tables: false + # Include headings + headings: true + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD025/single-title/single-h1 - Multiple top-level headings in the same document +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation - Trailing punctuation in heading +MD026: + # Punctuation characters + punctuation: ".,;:!。,;:!" + +# MD029/ol-prefix - Ordered list item prefix +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space - Spaces after list markers +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD033/no-inline-html - Inline HTML +MD033: + # Allowed elements + allowed_elements: [] + +# MD035/hr-style - Horizontal rule style +MD035: + # Horizontal rule style + style: "---" + +# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD036: + # Punctuation characters + punctuation: ".,;:!?。,;:!?" + +# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD044/proper-names - Proper names should have the correct capitalization +MD044: + # List of proper names + names: + - gitea + # Include code blocks + code_blocks: false + +# MD046/code-block-style - Code block style +MD046: + # Block style + style: "fenced" + +# MD048/code-fence-style - Code fence style +MD048: + # Code fence syle + style: "backtick" diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a00d0c5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "ansible.python.interpreterPath": "/bin/python", + "files.associations": { + "**/.gitea/**/*.yml": "yaml", + "**/.gitea/**/*.yaml": "yaml", + ".drone.yml": "yaml", + "docker-compose*.yml": "dockercompose", + "*.yml": "ansible", + "*.yaml": "ansible", + ".yamllint": "yaml", + ".yamllint.yml": "yaml", + ".yamllint.yaml": "yaml" + } +} \ No newline at end of file diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..f22686c --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,17 @@ +# +# Documentation: +# https://yamllint.readthedocs.io/en/stable/ +# + +rules: + brackets: + forbid: false + min-spaces-inside: 0 + max-spaces-inside: 2 + min-spaces-inside-empty: 0 + max-spaces-inside-empty: 0 + indentation: + spaces: 2 + indent-sequences: false + line-length: + max: 360 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..89dc507 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2025 Markus Pesch + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5b182e --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# sudo_users + +[![Ansible Role](https://img.shields.io/ansible/role/d/58433)](https://galaxy.ansible.com/volker_raschek/root) + +With following role can be created sudoers files in `/etc/sudoers.d`. For +example to grant a user special perimssions to execute a program as root. + +## Supported distributions + +- Arch Linux +- Debian +- Fedora +- RHEL +- Ubuntu 20.04 + +## Features + +- Installing sudo +- Configuring drop-on files in `/etc/sudoers.d` + +## Configuring + +In the default directory are examples how to configure the network stack. Copy the +defaults into your `host_vars` or `group_vars` and adapt the examples. diff --git a/default/main.yml b/default/main.yml new file mode 100644 index 0000000..bbbdbfc --- /dev/null +++ b/default/main.yml @@ -0,0 +1,12 @@ +--- + +root: {} +# password: "" +# ssh: +# config: +# - Host: "*" +# StrictHostKeyChecking: "no" +# UserKnownHostFile: /dev/null +# authorized_keys: +# - filename: markus@markus-pc.pub +# # command: "" # optional diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..4d40a5e --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,23 @@ +galaxy_info: + namespace: volker_raschek + role_name: "root" + author: "Markus Pesch" + description: Role to configure root + company: Cryptic Systems + license: MIT + min_ansible_version: "2.9" + platforms: + - name: ArchLinux + versions: + - all + - name: Ubuntu + versions: + - all + - name: Fedora + versions: + - "35" + + galaxy_tags: + - root + +dependencies: [] diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..84f88f7 --- /dev/null +++ b/renovate.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "local>volker.raschek/renovate-config:default#master", + "local>volker.raschek/renovate-config:container#master", + "local>volker.raschek/renovate-config:actions#master", + "local>volker.raschek/renovate-config:regexp#master" + ] +} \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..5457063 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,115 @@ +--- + +- name: Set or unset root password + block: + - name: Set root password + ansible.builtin.user: + name: root + password: "{{ root.password | password_hash('sha512') }}" + password_lock: false + when: root.password is defined and root.password | length > 0 and root.password != "!" + no_log: true + + - name: Update ansible_become_pass + ansible.builtin.set_fact: + ansible_become_pass: "{{ root.password }}" + when: root.password is defined and root.password | length > 0 and root.password != "!" + no_log: true + + - name: Lock root login + ansible.builtin.user: + name: root + password_lock: true + when: root.password is defined and root.password | length <= 0 + +- name: Create .ssh directory + ansible.builtin.file: + path: "/root/.ssh" + state: directory + owner: "root" + group: "root" + mode: "0700" + +- name: "Create authorized_keys file" + ansible.builtin.template: + src: root/.ssh/authorized_keys.j2 + dest: "/root/.ssh/authorized_keys" + owner: "root" + group: "root" + mode: "0600" + when: root.ssh is defined and + root.ssh.authorized_keys is defined and + root.ssh.authorized_keys | length > 0 + +- name: "Remove authorized_keys file" + ansible.builtin.file: + path: "/root/.ssh/authorized_keys" + state: absent + when: root.ssh is defined and + root.ssh.authorized_keys is defined and + root.ssh.authorized_keys | length <= 0 or + root.ssh is defined and + root.ssh.authorized_keys is not defined or + root.ssh is not defined + +- name: "Generate private and public SSH key" + when: root.ssh is defined and + ( + root.ssh.private_keys is not defined or + root.ssh.private_keys | length <= 0 + ) + block: + - name: "Check if private SSH key already exists" + ansible.builtin.stat: + path: "/root/.ssh/{{ inventory_hostname_short }}.key" + register: stat_result + - name: "Generate private SSH key" + community.crypto.openssh_keypair: + path: "/root/.ssh/{{ inventory_hostname_short }}.key" + type: ed25519 + size: 512 + state: present + comment: "root@{{ inventory_hostname_short }}" + force: false + when: not stat_result.stat.exists + +- name: "Create private and public SSH key" + when: root.ssh is defined and + root.ssh.private_keys is defined and + root.ssh.private_keys | length > 0 + block: + - name: "Create private SSH keys" + ansible.builtin.copy: + src: "{{ playbook_dir }}/ssh/private_keys/{{ item }}" + dest: "/root/.ssh/{{ item }}" + owner: "root" + group: "root" + mode: "0600" + with_items: + - "{{ root.ssh.private_keys }}" + + - name: "Extract public SSH keys from private keys" + ansible.builtin.shell: + args: + executable: /bin/bash + cmd: "ssh-keygen -y -f /root/.ssh/{{ item }} > /root/.ssh/{{ item }}.pub" + register: _root_ssh_pub_key_extraction + changed_when: _root_ssh_pub_key_extraction.rc == 0 + failed_when: _root_ssh_pub_key_extraction.rc > 0 + with_items: + - "{{ root.ssh.private_keys }}" + +- name: "Create custom SSH client config" + ansible.builtin.template: + src: root/.ssh/config.j2 + dest: /root/.ssh/config + owner: "root" + group: "root" + mode: "0644" + when: root.ssh.config is defined and root.ssh.config | length >= 0 + +- name: "Remove custom SSH client config" + ansible.builtin.file: + path: "/root/.ssh/config" + state: absent + when: root.ssh.config is not defined diff --git a/templates/root/.ssh/authorized_keys.j2 b/templates/root/.ssh/authorized_keys.j2 new file mode 100644 index 0000000..13d3c4f --- /dev/null +++ b/templates/root/.ssh/authorized_keys.j2 @@ -0,0 +1,10 @@ +# +# {{ ansible_managed }} +# +{% for authorized_key in root.ssh.authorized_keys %} +{% if authorized_key.command is defined and authorized_key.command | length > 0 %} +command="{{ authorized_key.command }}" {{ lookup('file', 'ssh/authorized_keys/' + authorized_key.filename ) }} +{% else %} +{{ lookup('file', 'ssh/authorized_keys/' + authorized_key.filename ) }} +{% endif %} +{% endfor %} diff --git a/templates/root/.ssh/config.j2 b/templates/root/.ssh/config.j2 new file mode 100644 index 0000000..208ba3a --- /dev/null +++ b/templates/root/.ssh/config.j2 @@ -0,0 +1,15 @@ +#jinja2: lstrip_blocks: True +# +# {{ ansible_managed }} +# + +{% for config in root.ssh.config %} +{% for property, value in config.items() %} +{% if property == "Host" %} +{{ property }} {{ value }} +{% else %} + {{ property }} {{ value }} +{% endif %} +{% endfor %} + +{% endfor %}