setup gitea as oidc provider for tool vault
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
.terraform
|
||||
.terraform.*
|
||||
.DS_Store
|
||||
node_modules/
|
||||
@@ -58,7 +58,8 @@ issues: http://example.com/issue/tracker
|
||||
# artifact. A pattern is matched from the relative path of the file or directory of the collection directory. This
|
||||
# uses 'fnmatch' to match the files or directories. Some directories and files like 'galaxy.yml', '*.pyc', '*.retry',
|
||||
# and '.git' are always filtered. Mutually exclusive with 'manifest'
|
||||
build_ignore: []
|
||||
build_ignore:
|
||||
- playwright/
|
||||
|
||||
# A dict controlling use of manifest directives used in building the collection artifact. The key 'directives' is a
|
||||
# list of MANIFEST.in style
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: hashicorp_vault
|
||||
# hosts: raspberries:&local
|
||||
hosts: localhost
|
||||
# debugger: on_failed
|
||||
|
||||
vars_prompt:
|
||||
- name: gitea_admin_password
|
||||
prompt: Enter gitea admin password
|
||||
unsafe: true # password can contain uncommon chars such as '{'
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Setup Hashicorp Vault
|
||||
include_role:
|
||||
name: hashicorp_vault
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: pgbouncer
|
||||
hosts: raspberries:&local
|
||||
|
||||
tasks:
|
||||
- ansible.builtin.ping:
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
- name: prometheus
|
||||
hosts: raspberries:&local
|
||||
|
||||
tasks:
|
||||
- ansible.builtin.ping:
|
||||
@@ -0,0 +1,10 @@
|
||||
vault_unseal_keys_path: ~/.arcodange/cluster-keys.json
|
||||
vault_unseal_keys_shares: 1
|
||||
vault_unseal_keys_key_threshold: 1 # keys_key_threshold <= keys_shares
|
||||
|
||||
vault_address: https://vault.arcodange.duckdns.org
|
||||
|
||||
vault_oidc_gitea_setupGiteaAppJS: '{{ role_path }}/files/playwright_setupGiteaApp.js'
|
||||
|
||||
gitea_admin_user: arcodange@gmail.com
|
||||
gitea_admin_password: "{{ undef(hint='You must specify the gitea user admin password') }}"
|
||||
@@ -0,0 +1,94 @@
|
||||
terraform {
|
||||
backend "gcs" {
|
||||
bucket = "arcodange-tf"
|
||||
prefix = "tools/hashicorp_vault/gitea_oidc"
|
||||
}
|
||||
}
|
||||
|
||||
variable "vault_address" {
|
||||
type = string
|
||||
default = "http://127.0.0.1:8200"
|
||||
}
|
||||
variable "vault_token" {
|
||||
type = string
|
||||
}
|
||||
variable "admin_email" {
|
||||
type = string
|
||||
default = "arcodange@gmail.com"
|
||||
}
|
||||
variable "gitea_app" {
|
||||
type = object({
|
||||
url = optional(string, "https://gitea.arcodange.duckdns.org/")
|
||||
id = string
|
||||
secret = string
|
||||
description = optional(string, "Arcodange Gitea Auth")
|
||||
})
|
||||
}
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
vault = {
|
||||
source = "vault"
|
||||
version = "4.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider vault {
|
||||
address = var.vault_address
|
||||
token = var.vault_token
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend" "gitea" {
|
||||
description = var.gitea_app.description
|
||||
default_role = "default"
|
||||
path = "gitea"
|
||||
type = "oidc"
|
||||
oidc_discovery_url = var.gitea_app.url
|
||||
oidc_client_id = var.gitea_app.id
|
||||
oidc_client_secret = var.gitea_app.secret
|
||||
bound_issuer = var.gitea_app.url
|
||||
tune {
|
||||
allowed_response_headers = []
|
||||
audit_non_hmac_request_keys = []
|
||||
audit_non_hmac_response_keys = []
|
||||
default_lease_ttl = "768h"
|
||||
listing_visibility = "unauth"
|
||||
max_lease_ttl = "768h"
|
||||
passthrough_request_headers = []
|
||||
token_type = "default-service"
|
||||
}
|
||||
}
|
||||
|
||||
resource "vault_jwt_auth_backend_role" "gitea" {
|
||||
backend = vault_jwt_auth_backend.gitea.path
|
||||
role_name = "default"
|
||||
token_policies = ["default"]
|
||||
|
||||
user_claim = "email"
|
||||
role_type = "oidc"
|
||||
allowed_redirect_uris = [
|
||||
"${var.vault_address}/ui/vault/auth/gitea/oidc/callback",
|
||||
]
|
||||
}
|
||||
|
||||
data "vault_policy_document" "admin" {
|
||||
rule {
|
||||
path = "*"
|
||||
capabilities = ["create", "read", "update", "delete", "list", "sudo"]
|
||||
description = "admin privileges"
|
||||
}
|
||||
}
|
||||
resource "vault_policy" "admin" {
|
||||
name = "admin"
|
||||
policy = data.vault_policy_document.admin.hcl
|
||||
}
|
||||
resource "vault_identity_entity" "admin" {
|
||||
name = var.admin_email
|
||||
policies = [vault_policy.admin.name]
|
||||
}
|
||||
resource "vault_identity_entity_alias" "admin" {
|
||||
name = var.admin_email
|
||||
mount_accessor = vault_jwt_auth_backend.gitea.accessor
|
||||
canonical_id = vault_identity_entity.admin.id
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import { chromium } from 'playwright';
|
||||
|
||||
/*
|
||||
Initialisation
|
||||
*/
|
||||
const username = process.env.GITEA_USER;
|
||||
const password = process.env.GITEA_PASSWORD;
|
||||
const debug = Boolean(process.env.DEBUG);
|
||||
const vaultAddress = process.env.VAULT_ADDRESS || 'http://localhost:8200';
|
||||
const giteaAddress = process.env.GITEA_ADDRESS || 'https://gitea.arcodange.duckdns.org';
|
||||
|
||||
if (!username || !password) {
|
||||
console.error('Veuillez définir les variables d\'environnement GITEA_USER et GITEA_PASSWORD.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const browser = await chromium.launch({
|
||||
headless: true,
|
||||
locale: "gb-GB", // before login gitea use gb-GB locale, after login it choose user locale
|
||||
logger: {
|
||||
isEnabled: (name, severity) => debug,
|
||||
log: (name, severity, message, args) => console.warn(`${severity}| ${name} :: ${message} __ ${args}`)
|
||||
},
|
||||
});
|
||||
const context = await browser.newContext({locale: "gb-GB"});
|
||||
const page = await context.newPage();
|
||||
|
||||
async function doLogin() {
|
||||
await page.goto(giteaAddress);
|
||||
await page.click('text=Sign In');
|
||||
await page.fill('input[name="user_name"]', username);
|
||||
await page.fill('input[name="password"]', password);
|
||||
await page.click('button:has-text("Sign In")');
|
||||
await page.waitForURL(giteaAddress);
|
||||
}
|
||||
|
||||
async function isLoggedIn() {
|
||||
return (
|
||||
await page.locator('text=Sign In').count() === 0
|
||||
&& await page.locator('.user-menu > .ui.header strong').count() > 0
|
||||
)
|
||||
}
|
||||
|
||||
// async function getLoggedUsername() {
|
||||
// const loggedInUser = await page.innerText('.user-menu > .ui.header strong');
|
||||
// if (debug) console.warn(`Connecté en tant que : ${loggedInUser}`);
|
||||
// return loggedInUser;
|
||||
// }
|
||||
|
||||
async function setupApp() {
|
||||
const appName = process.env.GITEA_APP_NAME || 'Arcodange Hashicorp Vault';
|
||||
|
||||
await page.goto(`${giteaAddress}/admin/applications`);
|
||||
|
||||
const applicationsPanel = await page.locator('.admin-setting-content');
|
||||
const applicationNameClass = await applicationsPanel.getByText('Git Credential Manager').getAttribute('class');
|
||||
const appNames = await applicationsPanel.locator(`.${applicationNameClass}`).allInnerTexts();
|
||||
|
||||
const app = {};
|
||||
|
||||
if (appNames.includes(appName)) {
|
||||
console.warn('app found');
|
||||
|
||||
const appElem = await applicationsPanel.locator(`.${applicationNameClass}`).getByText(appName).locator('xpath=../..');
|
||||
await appElem.highlight();
|
||||
await appElem.locator('a.button').click();
|
||||
|
||||
await page.waitForURL( new RegExp(`${giteaAddress}/admin/applications/oauth2/\\d+$`) );
|
||||
|
||||
await applicationsPanel.locator('form[action$="/regenerate_secret"] > button').click();
|
||||
} else {
|
||||
console.warn('app not found');
|
||||
await applicationsPanel.locator('input[name="application_name"]').fill(appName);
|
||||
await applicationsPanel.locator('textarea[name="redirect_uris"]').fill([
|
||||
`${vaultAddress}/ui/vault/auth/gitea/oidc/callback`
|
||||
].join('\n'));
|
||||
await applicationsPanel.locator('form[action="/admin/applications/oauth2"] > button').dblclick()
|
||||
|
||||
await page.waitForURL(`${giteaAddress}/admin/applications/oauth2`);
|
||||
}
|
||||
|
||||
app.id = await applicationsPanel.locator('input[id="client-id"]').getAttribute('value');
|
||||
app.secret = await applicationsPanel.locator('input[id="client-secret"]').getAttribute('value');
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
if (! await isLoggedIn()) await doLogin();
|
||||
// let _ = await getLoggedUsername()
|
||||
const app = await setupApp();
|
||||
|
||||
console.log(JSON.stringify(app));
|
||||
|
||||
await browser.close();
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
# Usage: prompt for gitea_admin_password in the calling playbook
|
||||
# vars_prompt:
|
||||
# - name: gitea_admin_password
|
||||
# prompt: Enter gitea admin password
|
||||
# unsafe: true # password can contain uncommon chars such as '{'
|
||||
|
||||
- set_fact:
|
||||
playwright_script: '{{ vault_oidc_gitea_setupGiteaAppJS }}'
|
||||
playwright_env:
|
||||
GITEA_USER: '{{ gitea_admin_user }}'
|
||||
GITEA_PASSWORD: '{{ gitea_admin_password }}'
|
||||
VAULT_ADDRESS: '{{ vault_address }}'
|
||||
|
||||
- include_role:
|
||||
name: arcodange.factory.playwright
|
||||
|
||||
- set_fact:
|
||||
gite_app: '{{ playwright_job.stdout | from_json }}'
|
||||
|
||||
volume_name: tofu-{{ ansible_date_time.iso8601.replace(':','-') }}
|
||||
|
||||
- name: use tofu to provision vault
|
||||
block:
|
||||
- shell: docker volume create {{ volume_name }}
|
||||
- shell: >-
|
||||
docker run --rm
|
||||
-v {{ volume_name }}:/tofu -w /tofu
|
||||
-v {{ role_path }}/files/hashicorp_vault.tf:/tofu/hashicorp_vault.tf
|
||||
-v ~/.config/gcloud:/root/.config/gcloud
|
||||
--entrypoint=''
|
||||
ghcr.io/opentofu/opentofu:latest
|
||||
{{ command }}
|
||||
loop:
|
||||
- tofu init -no-color
|
||||
- >-
|
||||
tofu apply -auto-approve -no-color
|
||||
-var='gitea_app={{ gite_app | to_json }}'
|
||||
-var='vault_address={{ vault_address }}'
|
||||
-var='vault_token={{ vault_root_token }}'
|
||||
loop_control:
|
||||
loop_var: command
|
||||
|
||||
always:
|
||||
- shell: docker volume rm {{ volume_name }}
|
||||
@@ -0,0 +1,34 @@
|
||||
- name: list vault servers to unseal
|
||||
ansible.builtin.command:
|
||||
kubectl -n tools get pods -l app.kubernetes.io/instance=hashicorp-vault -l component=server -o jsonpath="{.items[*]['.metadata.name']}"
|
||||
register: vault_servers_cmd
|
||||
changed_when: False
|
||||
|
||||
- ansible.builtin.set_fact:
|
||||
vault_servers: '{{ vault_servers_cmd.stdout.split() }}'
|
||||
|
||||
- ansible.builtin.shell:
|
||||
kubectl -n tools exec {{ vault_servers[0] }} -- vault operator init -status
|
||||
register: vault_init_status
|
||||
failed_when: vault_init_status.rc == 1
|
||||
changed_when: False
|
||||
|
||||
- when: vault_init_status.rc == 2
|
||||
block:
|
||||
- ansible.builtin.debug:
|
||||
msg: not initialized
|
||||
- ansible.builtin.command: >-
|
||||
kubectl -n tools exec {{ vault_servers[0] }} -- vault operator init
|
||||
-format=json
|
||||
-key-shares={{ vault_unseal_keys_shares }}
|
||||
-key-threshold={{ vault_unseal_keys_key_threshold }}
|
||||
register: vault_keys_cmd
|
||||
|
||||
- ansible.builtin.file:
|
||||
state: directory
|
||||
path: '{{ vault_unseal_keys_path | dirname }}'
|
||||
mode: '700'
|
||||
- ansible.builtin.copy:
|
||||
content: '{{ vault_keys_cmd.stdout }}'
|
||||
dest: '{{ vault_unseal_keys_path }}'
|
||||
mode: '600'
|
||||
@@ -0,0 +1,15 @@
|
||||
- name: Init (first time only)
|
||||
include_tasks: init.yml
|
||||
- name: Unseal (required on reboot)
|
||||
include_tasks: unseal.yml
|
||||
|
||||
- block:
|
||||
- name: Generate root token
|
||||
include_tasks: new_root_token.yml
|
||||
- name: Setup gitea oidc auth
|
||||
include_tasks: gitea_oidc_auth.yml
|
||||
always:
|
||||
- name: Revoke root token
|
||||
include_tasks: revoke_token.yml
|
||||
vars:
|
||||
vault_token_to_revoke: '{{ vault_root_token }}'
|
||||
@@ -0,0 +1,32 @@
|
||||
- name: 'Generate New Root Token'
|
||||
include_tasks: vault_cmd.yml
|
||||
vars:
|
||||
vault_cmd: '{{ item.cmd }}'
|
||||
vault_cmd_output_var: '{{ item.save }}'
|
||||
vault_cmd_json_attr: '{{ item.json_attr | default("") }}'
|
||||
vault_cmd_can_fail: '{{ item.can_fail | default(false) }}'
|
||||
|
||||
vault_unseal_keys: "{{ (lookup('ansible.builtin.file', vault_unseal_keys_path) | from_json)['unseal_keys_b64'] }}"
|
||||
cmds:
|
||||
- cmd: vault token revoke -self
|
||||
save: false
|
||||
can_fail: true
|
||||
- cmd: vault operator generate-root -generate-otp
|
||||
save: vault_generate_root_otp
|
||||
- cmd: !unsafe vault operator generate-root -cancel -otp {{ vault_generate_root_otp }}
|
||||
- cmd: !unsafe vault operator generate-root -init -otp {{ vault_generate_root_otp }}
|
||||
save: vault_generate_root_nonce
|
||||
json_attr: 'nonce'
|
||||
- |- # not yet tested with vault_unseal_keys_key_threshold > 1 (saving not available encoded_root_token might break)
|
||||
{{
|
||||
vault_unseal_keys[:vault_unseal_keys_key_threshold] | map('regex_replace', '(.+)', '{
|
||||
"cmd": "vault operator generate-root -nonce {{ vault_generate_root_nonce }} \1",
|
||||
"save": "vault_generate_root_encoded_token",
|
||||
"json_attr": "encoded_root_token"
|
||||
}') | map("from_json") | list
|
||||
}}
|
||||
- cmd: !unsafe vault operator generate-root -decode {{ vault_generate_root_encoded_token }} -otp {{ vault_generate_root_otp }}
|
||||
save: vault_root_token
|
||||
- cmd: !unsafe vault login {{ vault_root_token }}
|
||||
save: false
|
||||
loop: '{{ cmds | flatten }}'
|
||||
@@ -0,0 +1,3 @@
|
||||
- shell: >-
|
||||
kubectl exec -n tools hashicorp-vault-0 --
|
||||
vault token revoke {{ vault_token_to_revoke | default('-self') }}
|
||||
@@ -0,0 +1,23 @@
|
||||
- debug:
|
||||
msg: reading from {{ vault_unseal_keys_path }}
|
||||
- ansible.builtin.set_fact:
|
||||
vault_keys: "{{ lookup('ansible.builtin.file', vault_unseal_keys_path) | from_json }}"
|
||||
|
||||
- ansible.builtin.command:
|
||||
kubectl -n tools exec {{ vault_server__key[0] }} -- vault operator unseal {{ vault_server__key[1] }}
|
||||
loop: '{{ vault_servers | product(vault_keys["unseal_keys_b64"]) }}'
|
||||
loop_control:
|
||||
loop_var: vault_server__key
|
||||
label: 'unsealing {{ vault_server__key[0] }}'
|
||||
|
||||
- block:
|
||||
- ansible.builtin.command:
|
||||
kubectl -n tools exec {{ vault_servers[0] }} -- vault login {{ vault_keys["root_token"] }}
|
||||
|
||||
- name: Revoke root token
|
||||
include_tasks: revoke_token.yml
|
||||
vars:
|
||||
vault_token_to_revoke: '-self'
|
||||
rescue:
|
||||
- debug:
|
||||
msg: 'initial root token already revoked'
|
||||
@@ -0,0 +1,23 @@
|
||||
- set_fact:
|
||||
vault_cmd_interpolated: '{{ vault_cmd }}'
|
||||
|
||||
- name: 'variable interpolation in vault_cmd'
|
||||
set_fact:
|
||||
vault_cmd_interpolated: "{{ vault_cmd_interpolated | regex_replace('\\{\\{ *' + varname + ' *\\}\\}', lookup('vars', varname, default='')) }}"
|
||||
loop: "{{ vault_cmd | regex_findall('\\{\\{ *([a-zA-Z_][a-zA-Z0-9_]*) *\\}\\}') }}"
|
||||
loop_control:
|
||||
loop_var: varname
|
||||
|
||||
- ansible.builtin.shell: >-
|
||||
kubectl exec -n tools hashicorp-vault-0 -- {{ 'env VAULT_FORMAT=json' if vault_cmd_json_attr != '' else '' }}
|
||||
{{ vault_cmd_interpolated }}
|
||||
register: vault_cmd_output
|
||||
ignore_errors: '{{ vault_cmd_can_fail }}'
|
||||
|
||||
|
||||
- when: vault_cmd_output_var is not false
|
||||
ansible.builtin.set_fact:
|
||||
'{{ vault_cmd_output_var | default("vault_cmd_out") }}' : |-
|
||||
{{ vault_cmd_output.stdout if not vault_cmd_json_attr else
|
||||
(vault_cmd_output.stdout | from_json)[vault_cmd_json_attr]
|
||||
}}
|
||||
@@ -1,6 +1,3 @@
|
||||
---
|
||||
- name: pgbouncer
|
||||
ansible.builtin.import_playbook: pgbouncer.yml
|
||||
|
||||
- name: prometheus
|
||||
ansible.builtin.import_playbook: prometheus.yml
|
||||
- name: hashicorp_vault
|
||||
ansible.builtin.import_playbook: hashicorp_vault.yml
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
playwright_script: '{{ {{ role_path }}/files/loginGitea.js }}'
|
||||
playwright_use_docker: true
|
||||
playwright_version: '1.47.0'
|
||||
playwright_docker_image: playwright:{{ playwright_version }}
|
||||
25
ansible/arcodange/factory/roles/playwright/files/Dockerfile
Normal file
25
ansible/arcodange/factory/roles/playwright/files/Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
||||
# Utiliser l'image officielle Node.js avec Playwright
|
||||
FROM mcr.microsoft.com/playwright:v1.38.0-jammy
|
||||
|
||||
ARG playwright_version=1.47.0
|
||||
|
||||
# Définir le répertoire de travail
|
||||
WORKDIR /app
|
||||
|
||||
# Copier les fichiers package.json et package-lock.json
|
||||
COPY v${playwright_version}/package*.json ./
|
||||
|
||||
# Installer les dépendances Node.js
|
||||
RUN npm install
|
||||
|
||||
# Installer les navigateurs nécessaires pour Playwright
|
||||
RUN npx playwright install
|
||||
|
||||
# Copier le script par défaut
|
||||
COPY loginGitea.js ./script.js
|
||||
|
||||
# Commande pour exécuter le script
|
||||
CMD ["node", "script.js"]
|
||||
|
||||
# RUN WITH
|
||||
# docker run -v $PWD/loginGitea.js:/app/loginGitea.js --rm playwright-gitea sh -c "sed 's/headless: false/headless: true/' loginGitea.js | node --input-type=module"
|
||||
@@ -0,0 +1,55 @@
|
||||
import { chromium } from 'playwright';
|
||||
|
||||
/*
|
||||
Initialisation
|
||||
*/
|
||||
const username = process.env.GITEA_USER;
|
||||
const password = process.env.GITEA_PASSWORD;
|
||||
const debug = Boolean(process.env.DEBUG);
|
||||
const vaultAddress = process.env.VAULT_ADDRESS || 'http://localhost:8200';
|
||||
const giteaAddress = process.env.GITEA_ADDRESS || 'https://gitea.arcodange.duckdns.org';
|
||||
|
||||
if (!username || !password) {
|
||||
console.error('Veuillez définir les variables d\'environnement GITEA_USER et GITEA_PASSWORD.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const browser = await chromium.launch({
|
||||
headless: true,
|
||||
locale: "gb-GB", // before login gitea use gb-GB locale, after login it choose user locale
|
||||
logger: {
|
||||
isEnabled: (name, severity) => debug,
|
||||
log: (name, severity, message, args) => console.warn(`${severity}| ${name} :: ${message} __ ${args}`)
|
||||
},
|
||||
});
|
||||
const context = await browser.newContext({locale: "gb-GB"});
|
||||
const page = await context.newPage();
|
||||
|
||||
async function doLogin() {
|
||||
await page.goto(giteaAddress);
|
||||
await page.click('text=Sign In');
|
||||
await page.fill('input[name="user_name"]', username);
|
||||
await page.fill('input[name="password"]', password);
|
||||
await page.click('button:has-text("Sign In")');
|
||||
await page.waitForURL(giteaAddress);
|
||||
}
|
||||
|
||||
async function isLoggedIn() {
|
||||
return (
|
||||
await page.locator('text=Sign In').count() === 0
|
||||
&& await page.locator('.user-menu > .ui.header strong').count() > 0
|
||||
)
|
||||
}
|
||||
|
||||
async function getLoggedUsername() {
|
||||
const loggedInUser = await page.innerText('.user-menu > .ui.header strong');
|
||||
if (debug) console.warn(`Connecté en tant que : ${loggedInUser}`);
|
||||
return loggedInUser;
|
||||
}
|
||||
|
||||
if (! await isLoggedIn()) await doLogin();
|
||||
const giteaUser = await getLoggedUsername()
|
||||
|
||||
console.log(JSON.stringify({giteaUser}));
|
||||
|
||||
await browser.close();
|
||||
70
ansible/arcodange/factory/roles/playwright/files/v1.47.0/package-lock.json
generated
Normal file
70
ansible/arcodange/factory/roles/playwright/files/v1.47.0/package-lock.json
generated
Normal file
@@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "playwright",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "playwright",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"playwright": "^1.47.0",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.47.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.0.tgz",
|
||||
"integrity": "sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.47.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.47.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.0.tgz",
|
||||
"integrity": "sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
|
||||
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "playwright",
|
||||
"version": "1.0.0",
|
||||
"main": "loginGitea.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "node loginGitea.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "arcodange@gmail.com",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"playwright": "^1.47.0"
|
||||
}
|
||||
}
|
||||
25
ansible/arcodange/factory/roles/playwright/tasks/main.yml
Normal file
25
ansible/arcodange/factory/roles/playwright/tasks/main.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
- when: playwright_use_docker
|
||||
block:
|
||||
- name: Build {{ playwright_docker_image }} docker image
|
||||
community.docker.docker_image_build:
|
||||
name: '{{ playwright_docker_image }}'
|
||||
path: '{{ role_path }}/files/'
|
||||
args:
|
||||
playwright_version: '{{ playwright_version }}'
|
||||
- name: run {{ playwright_script | basename }}
|
||||
vars:
|
||||
cmd_env: '{{ playwright_env | default({}) }}'
|
||||
env_arguments: >-
|
||||
{% for e in (cmd_env.keys() | zip( cmd_env.values() ) | map('join', '=') ) %}
|
||||
-e {{ e }}
|
||||
{% endfor %}
|
||||
|
||||
ansible.builtin.shell: >-
|
||||
docker run
|
||||
-v {{ playwright_script }}:/app/script.js
|
||||
{{ env_arguments }}
|
||||
--rm
|
||||
{{ playwright_docker_image }}
|
||||
# sh -c "sed 's/headless: *false/headless: true/' script.js | node --input-type=module"
|
||||
|
||||
register: playwright_job
|
||||
56
doc/adr/04_tool_hashicorp_vault.md
Normal file
56
doc/adr/04_tool_hashicorp_vault.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# [Bases](./README.md)
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
### Hashicorp Vault
|
||||
|
||||
>[!WARNING]
|
||||
>L'unsealKey, le vaultRootToken initial et l'authentification au backend terraform sont pour le moment configurés sur le controleur ansible (Macbook Pro).
|
||||
|
||||
>[!NOTE]
|
||||
> Vault est déployé via [argo cd](https://gitea.arcodange.duckdns.org/arcodange-org/tools/src/branch/main/hashicorp-vault)
|
||||
|
||||
```mermaid
|
||||
%%{init: { 'logLevel': 'debug', 'theme': 'base',
|
||||
'sequence': {
|
||||
'showSequenceNumbers': true,
|
||||
'mirrorActors': false
|
||||
}
|
||||
}}%%
|
||||
sequenceDiagram
|
||||
participant Ansible
|
||||
participant Gitea
|
||||
participant Vault
|
||||
|
||||
Note right of Vault: Argo CD App <br> versioned in Gitea
|
||||
|
||||
rect rgb(191, 223, 255)
|
||||
|
||||
Ansible ->> Gitea : setupAdminAccount(adminPassword)
|
||||
Ansible ->> Vault : init
|
||||
activate Vault
|
||||
Vault -->> Ansible : (unsealKey, vaultRootToken)
|
||||
deactivate Vault
|
||||
Ansible ->> Vault: unseal(unsealKey)
|
||||
Ansible ->> Vault: revoke vaultRootToken
|
||||
|
||||
rect rgb(255, 266, 255)
|
||||
|
||||
Ansible ->> Gitea : setupApp(adminPassword)
|
||||
activate Gitea
|
||||
Note left of Gitea: docker playwright
|
||||
deactivate Gitea
|
||||
Gitea -->> Ansible : app(id,secret)
|
||||
|
||||
Ansible ->> Vault : generate vaultRootToken
|
||||
Ansible ->> Vault : enable oidc auth backend with app(id,secret) <br> give admin policy to admin user
|
||||
activate Vault
|
||||
Note left of Vault: docker tofu(vaultRootToken)
|
||||
deactivate Vault
|
||||
Ansible ->> Vault: revoke vaultRootToken
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
```
|
||||
@@ -9,11 +9,18 @@
|
||||
- [x] setup postgres
|
||||
- [x] setup gitea
|
||||
- [x] setup mail alert
|
||||
- [ ] [setup gitea runners, Argo CD](./03_cicd_gitea_action_argocd.md)
|
||||
- [x] [setup gitea runners, Argo CD](./03_cicd_gitea_action_argocd.md)
|
||||
- [x] sync git repo with github/gitlab
|
||||
- [ ] docker hub
|
||||
- [ ] gitea packages
|
||||
- [x] gitea packages
|
||||
- [ ] devsecops tools
|
||||
- [x] [hashicorp vault](./04_tool_hashicorp_vault.md)
|
||||
- [ ] terrakube
|
||||
- [ ] prometheus/grafana
|
||||
- [ ] ansible AWX
|
||||
- [ ] setup hello world web app
|
||||
- [ ] manage postgres credentials
|
||||
- [ ] protect public endpoint (crowdsec)
|
||||
|
||||
> [!NOTE]
|
||||
> Reference: [Arcodange _**Factory**_ Ansible Collection](/ansible/arcodange/factory/README.md)
|
||||
|
||||
Reference in New Issue
Block a user