├── .codacy.yml
├── .codeclimate.yml
├── .coveragerc
├── .editorconfig
├── .gitignore
├── .gitlab-ci.yml
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── api
├── __init__.py
├── admin.py
├── apps.py
├── auth
│ ├── __init__.py
│ ├── adapter.py
│ └── serializers.py
├── authentication.py
├── filters.py
├── forms.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_remove_authorisedapp_scopes_delete_scope.py
│ ├── 0003_rename_owner_authorisedapp_user.py
│ ├── 0004_alter_authorisedapp_name_and_more.py
│ └── __init__.py
├── mixins.py
├── models.py
├── permissions.py
├── serializers.py
├── templates
│ └── rest_framework
│ │ ├── api.html
│ │ └── login.html
├── tests
│ ├── __init__.py
│ ├── api
│ │ ├── __init__.py
│ │ ├── auth
│ │ │ ├── __init__.py
│ │ │ └── test_auth.py
│ │ ├── test_certificates.py
│ │ ├── test_retrieve_crl.py
│ │ └── tokens
│ │ │ ├── __init__.py
│ │ │ └── test_tokens.py
│ ├── base.py
│ ├── factories.py
│ └── test_factories.py
├── tokens
│ ├── __init__.py
│ ├── serializers.py
│ ├── urls.py
│ └── views.py
├── urls.py
├── utils.py
└── views.py
├── bounca
├── __init__.py
├── management
│ ├── __init__.py
│ └── commands
│ │ ├── __init__.py
│ │ └── site.py
├── settings.py
├── urls.py
└── wsgi.py
├── build-front.sh
├── build-package.sh
├── certificate_engine
├── __init__.py
├── apps.py
├── ssl
│ ├── __init__.py
│ ├── certificate.py
│ ├── crl.py
│ ├── info.py
│ └── key.py
├── tests
│ ├── __init__.py
│ ├── helpers.py
│ ├── test_client_certificate.py
│ ├── test_codesigning_certificate.py
│ ├── test_crl.py
│ ├── test_ed25519_key.py
│ ├── test_intermediate_certificate.py
│ ├── test_oscp_certificate.py
│ ├── test_root_certificate.py
│ ├── test_rsa_key.py
│ └── test_server_certificate.py
└── types.py
├── changelog.md
├── docker-compose.yml
├── docs
├── Makefile
└── source
│ ├── _static
│ └── bounca.css
│ ├── _templates
│ ├── launchpage.html
│ └── layout.html
│ ├── bounca
│ ├── contribution.rst
│ ├── features.rst
│ └── support.rst
│ ├── conf.py
│ ├── demo
│ ├── nginx_client_auth
│ │ ├── certs
│ │ │ ├── BounCA_Int_Root.intermediate-chain.pem
│ │ │ ├── demo1.client_cert
│ │ │ │ ├── crlchain.pem
│ │ │ │ ├── demo1-chain.pem
│ │ │ │ ├── demo1.key
│ │ │ │ ├── demo1.p12
│ │ │ │ ├── demo1.pem
│ │ │ │ ├── intermediate.pem
│ │ │ │ ├── intermediate_root-chain.pem
│ │ │ │ └── rootca.pem
│ │ │ ├── demo2.client_cert
│ │ │ │ ├── crlchain.pem
│ │ │ │ ├── demo2-chain.pem
│ │ │ │ ├── demo2.key
│ │ │ │ ├── demo2.p12
│ │ │ │ ├── demo2.pem
│ │ │ │ ├── intermediate.pem
│ │ │ │ ├── intermediate_root-chain.pem
│ │ │ │ └── rootca.pem
│ │ │ ├── int.crl.pem
│ │ │ ├── localhost-chain.pem
│ │ │ ├── localhost.key
│ │ │ ├── root.crl.pem
│ │ │ ├── root_int.crl.pem
│ │ │ └── rootca.pem
│ │ ├── docker-compose.yml
│ │ ├── nginx.conf
│ │ └── www
│ │ │ └── index.html
│ └── nginx_ssl
│ │ ├── certs
│ │ ├── localhost-chain.pem
│ │ ├── localhost.key
│ │ └── rootca.pem
│ │ ├── docker-compose.yml
│ │ ├── nginx.conf
│ │ └── www
│ │ └── index.html
│ ├── getting_started.rst
│ ├── images
│ ├── BounCA-logo.png
│ ├── generate-ca-certificates
│ │ ├── 1-empty-root-dashboard.png
│ │ ├── 10-inspect-intermediate-certificate.png
│ │ ├── 11-inspect-intermediate-certificate-crl-ocsp.png
│ │ ├── 2-create-root-certificate.png
│ │ ├── 20-install-root-pem-certificate.png
│ │ ├── 20-listed-root-pem-certificate.png
│ │ ├── 21-inspect-root-pem-certificate.png
│ │ ├── 22-trust-root-ca-pem.png
│ │ ├── 24-trusted-self-signed-root-ca-pem.png
│ │ ├── 26-root-ca-is-trusted.png
│ │ ├── 27-generate-app-token.png
│ │ ├── 3-create-root-certificate-crl.png
│ │ ├── 4-root-certificate-generated.png
│ │ ├── 5-inspect-root-certificate.png
│ │ ├── 6-inspect-root-certificate-X.509v3-extensions.png
│ │ ├── 7-enter-root-ca.png
│ │ ├── 8-generate-intermediate-certificate.png
│ │ ├── 9-generate-intermediate-certificate-enter-passphrases.png
│ │ └── 9-generated-intermediate-ca.png
│ ├── generate-client-certificate
│ │ ├── 12-enter-int-ca.png
│ │ ├── 13-open-client-certificate-create-form.png
│ │ ├── 14-fill-in-the-data.png
│ │ ├── 15-enter-the-passphrase.png
│ │ ├── 16-create-a-second-client-certificate.png
│ │ ├── 17-enter-passphrase-of-second-certificate.png
│ │ ├── 18-overview-generated-certificates.png
│ │ ├── 20-enter-passphrase-of-intermediate.png
│ │ ├── 21-revoked-demo2-certificate.png
│ │ ├── 22-download-intermediate-chain-and-crl.png
│ │ ├── 31-verify-demo1-2-certificates.png
│ │ ├── 32-content-of-intermediate-crl-file.png
│ │ ├── 33-check-revoked-certificate.png
│ │ ├── 34-no-client-cert.png
│ │ ├── 35-valid-client-cert.png
│ │ ├── 36-revoked-client-cert.png
│ │ ├── 40-adding-client-certificate-to-keychain-of-macOS.png
│ │ ├── 41-added-client-certificate-to-keychain-of-macOS.png
│ │ ├── 42-inspect-client-certificate.png
│ │ ├── 43-visit-mTLS-site-safari.png
│ │ ├── 44-granted-mTLS-safari.png
│ │ ├── 45-visit-mTLS-chrome.png
│ │ ├── 46-granted-mTLS-chrome.png
│ │ ├── 47-certificate-management-firefox.png
│ │ ├── 48-import-pkcs12-in-firefox.png
│ │ ├── 49-client-certificate-added-in-firefox.png
│ │ ├── 50-visit-mTLS-firefox.png
│ │ └── 51-granted-mTLS-firefox.png
│ ├── generate-mail-certificate
│ │ ├── 12-enter-int-ca.png
│ │ ├── 14-fill-in-the-data.png
│ │ ├── 15-enter-the-passphrase.png
│ │ ├── 16-generated-smime-certificate.png
│ │ ├── 17-inspect-subject-client-certificate.png
│ │ ├── 18-inspect-subject-alt-names-certificate.png
│ │ ├── 19-install-client-certificate.png
│ │ ├── 20-create-signed-mail.png
│ │ ├── 21-received-signed-mail.png
│ │ ├── 22-received-signed-mail-thunderbird-not-trusted.png
│ │ ├── 23-add-root-certificate-thunderbird.png
│ │ ├── 24-trust-root-certificate-thunderbird.png
│ │ ├── 25-received-signed-mail-trusted-thunderbird.png
│ │ ├── 26-add-client-certificate-to-thunderbird.png
│ │ ├── 27-select-p12-file-thunderbird.png
│ │ ├── 28-client-certificate-added-thunderbird.png
│ │ ├── 29-select-client-certificate-to-sign-and-encrypt-mail-thunderbird.png
│ │ ├── 30-client-certificate-configured-thunderbird.png
│ │ ├── 31-send-signed-mail-thunderbird.png
│ │ ├── 32-send-encrypted-mail-Mail.png
│ │ └── 33-received-encrypted-mail-Firefox.png
│ ├── generate-server-certificate
│ │ ├── 12-enter-int-ca.png
│ │ ├── 13-copy-data-from-intermediate-certificate.png
│ │ ├── 13-create-ssl-server-certificate.png
│ │ ├── 14-enter-passphrase.png
│ │ ├── 14-enter-subject-alternative-names.png
│ │ ├── 15-inspect-server-certificate.png
│ │ ├── 15-server-certificate-generated.png
│ │ ├── 16-inspect-server-certificate-crl-ocsp.png
│ │ ├── 18-ssl-certificate-zip-package.png
│ │ ├── 19-check-ssl-certificate-chain.png
│ │ ├── 26-root-ca-is-trusted.png
│ │ ├── 28-visit-website-trusted-ssl-connection-https.png
│ │ ├── 30-renew-certificate.png
│ │ ├── 31-renew-certificate-form.png
│ │ └── 32-certificate-renewed.png
│ ├── hex.png
│ ├── hexa.png
│ ├── ico
│ │ ├── android-chrome-144x144.png
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-36x36.png
│ │ ├── android-chrome-48x48.png
│ │ ├── android-chrome-72x72.png
│ │ ├── android-chrome-96x96.png
│ │ ├── apple-touch-icon-114x114.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-144x144.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── apple-touch-icon-57x57.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-72x72.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── apple-touch-icon.png
│ │ ├── browserconfig.xml
│ │ ├── favicon-16x16.png
│ │ ├── favicon-194x194.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon-96x96.png
│ │ ├── favicon.ico
│ │ ├── manifest.json
│ │ ├── mstile-144x144.png
│ │ ├── mstile-150x150.png
│ │ ├── mstile-310x150.png
│ │ ├── mstile-310x310.png
│ │ ├── mstile-70x70.png
│ │ └── safari-pinned-tab.svg
│ ├── install_root_certificate
│ │ ├── 1_chrome_open_settings.png
│ │ ├── 1_firefox_open_settings_page.png
│ │ ├── 20-install-root-pem-certificate.png
│ │ ├── 20-listed-root-pem-certificate.png
│ │ ├── 21-inspect-root-pem-certificate.png
│ │ ├── 22-trust-root-ca-pem.png
│ │ ├── 24-trusted-self-signed-root-ca-pem.png
│ │ ├── 26-root-ca-is-trusted.png
│ │ ├── 2_chrome_click_on_advanced_settings_and_go_to_certificates.png
│ │ ├── 2_firefox_click_on_advanced_settings_and_go_to_certificates.png
│ │ ├── 3_chrome_click_on_authorities_and_press_import_button.png
│ │ ├── 3_firefox_import_the_root_certificate.png
│ │ ├── 4_chrome_select_the_root_certificate_file.png
│ │ ├── 4_firefox_select_the_root_certificate_file.png
│ │ ├── 5_chrome_add_the_certificate_and_select_trust_rules.png
│ │ ├── 5_firefox_select_the_trust_rules.png
│ │ ├── 6_chrome_certificate_is_added_to_authorities_list.png
│ │ ├── 6_firefox_the_root_certificate_has_been_added.png
│ │ ├── 7_chrome_inspect_the_certificate_by_clicking_on_view_button.png
│ │ ├── 7_firefox_inspect_the_root_certificate.png
│ │ ├── 8_chrome_visit_self-signed_website_and_verify_it_is_trusted.png
│ │ ├── 8_firefox_visit_self-signed_website_and_verify_it_is_trusted.png
│ │ ├── ios_certificate_installed.jpg
│ │ ├── ios_open_certificate.jpg
│ │ └── ios_trust_new_certificate.jpg
│ ├── main
│ │ ├── bounca
│ │ │ ├── adding_new_intermediate_certificate.png
│ │ │ ├── client_server_certificate_overview.png
│ │ │ ├── intermediate_certificate_overview.png
│ │ │ ├── revoke_certificate.png
│ │ │ ├── revoked_certificate_overview.png
│ │ │ ├── root_ca_dashboard.png
│ │ │ ├── root_certificate_info.png
│ │ │ ├── ssl_dashboard_bounca.png
│ │ │ └── validated_certificate_chain.png
│ │ ├── create.png
│ │ ├── easy.png
│ │ ├── integrate.png
│ │ ├── manage.png
│ │ ├── private.png
│ │ ├── triangulated_grid.png
│ │ └── world.png
│ ├── readme
│ │ └── ssl_dashboard_bounca.png
│ └── vpn-configuration
│ │ ├── 12-enter-int-ca.png
│ │ ├── 13-create-openvpn-server-certificate.png
│ │ ├── 14-passphrase-openvpn-server-certificate.png
│ │ ├── 15-generate-dh-params.png
│ │ ├── 20-create-openvpn-client-certificate.png
│ │ ├── 20-passphrase-openvpn-client-certificate.png
│ │ ├── 31-OpenVPN-dashboard-OpenWRT.png
│ │ ├── 32-Demo-VPN-uploaded.png
│ │ ├── 33-Inspect-config-Demo-VPN.png
│ │ ├── 34-Save-Apply-and-start-Demo-VPN.png
│ │ ├── 35-Add-firewall-rule-accepting-UDP-OpenVPN.png
│ │ ├── 36-Allow-tun-interface-in-local-LAN-zone.png
│ │ ├── 36a-Allow-tun-interface-in-local-LAN-zone.png
│ │ ├── 40-import-ovpn-file.png
│ │ ├── 41-imported-profile.png
│ │ ├── 42-disconnected-profile.png
│ │ ├── 43-enter-passphrase.png
│ │ ├── 44-connected-vpn.png
│ │ └── 45-browse-to-internal-network.png
│ ├── include_files.rst
│ ├── index.rst
│ └── tutorials
│ ├── create_certificate_authority.rst
│ ├── create_client_certificate_browser.rst
│ ├── create_mail_certificate.rst
│ ├── create_server_certificate_webserver.rst
│ ├── install_root_certificate.rst
│ └── vpn_configuration.rst
├── etc
├── bounca
│ └── services.yaml.example
├── nginx
│ └── bounca
└── uwsgi
│ └── bounca.ini
├── front
├── .babelrc
├── .env
├── .env.production
├── .eslintignore
├── .eslintrc.js
├── .postcssrc.js
├── Makefile
├── README.md
├── babel.config.js
├── package.json
├── public
│ ├── favicon.ico
│ ├── ico
│ │ ├── android-chrome-144x144.png
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-36x36.png
│ │ ├── android-chrome-48x48.png
│ │ ├── android-chrome-72x72.png
│ │ ├── android-chrome-96x96.png
│ │ ├── apple-touch-icon-114x114.png
│ │ ├── apple-touch-icon-120x120.png
│ │ ├── apple-touch-icon-144x144.png
│ │ ├── apple-touch-icon-152x152.png
│ │ ├── apple-touch-icon-180x180.png
│ │ ├── apple-touch-icon-57x57.png
│ │ ├── apple-touch-icon-60x60.png
│ │ ├── apple-touch-icon-72x72.png
│ │ ├── apple-touch-icon-76x76.png
│ │ ├── apple-touch-icon-precomposed.png
│ │ ├── apple-touch-icon.png
│ │ ├── browserconfig.xml
│ │ ├── favicon-16x16.png
│ │ ├── favicon-194x194.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon-96x96.png
│ │ ├── manifest.json
│ │ ├── mstile-144x144.png
│ │ ├── mstile-150x150.png
│ │ ├── mstile-310x150.png
│ │ ├── mstile-310x310.png
│ │ ├── mstile-70x70.png
│ │ └── safari-pinned-tab.svg
│ └── index.html
├── src
│ ├── App.vue
│ ├── api
│ │ ├── apptokens.js
│ │ ├── auth.js
│ │ ├── certificates.js
│ │ ├── profile.js
│ │ └── session.js
│ ├── assets
│ │ └── img
│ │ │ └── BounCA-logo.png
│ ├── components
│ │ ├── auth
│ │ │ ├── EmailVerify.vue
│ │ │ ├── Login.vue
│ │ │ ├── PasswordForgot.vue
│ │ │ ├── PasswordReset.vue
│ │ │ ├── ResendEmail.vue
│ │ │ └── Signup.vue
│ │ ├── core
│ │ │ ├── Drawer.vue
│ │ │ ├── Footer.vue
│ │ │ └── Toolbar.vue
│ │ ├── dashboard
│ │ │ ├── Certificate.vue
│ │ │ ├── Intermediate.vue
│ │ │ ├── Overview.vue
│ │ │ ├── Root.vue
│ │ │ └── user
│ │ │ │ └── UserProfile.vue
│ │ ├── error
│ │ │ └── NotFound.vue
│ │ ├── forms
│ │ │ ├── Certificate.vue
│ │ │ ├── EmailVerify.vue
│ │ │ ├── IntermediateCert.vue
│ │ │ ├── RenewCertificate.vue
│ │ │ ├── RootCert.vue
│ │ │ └── user
│ │ │ │ ├── AddToken.vue
│ │ │ │ ├── ChangePassword.vue
│ │ │ │ └── ChangeProfile.vue
│ │ └── index.js
│ ├── main.js
│ ├── plugins
│ │ └── vuetify.js
│ ├── router
│ │ ├── auth.js
│ │ ├── dashboard.js
│ │ ├── home.js
│ │ └── index.js
│ ├── store
│ │ ├── auth.js
│ │ ├── dashboard.js
│ │ ├── index.js
│ │ └── version.js
│ └── views
│ │ ├── Auth.vue
│ │ ├── Dashboard.vue
│ │ └── Public.vue
└── vue.config.js
├── graphics
└── logo
│ ├── BounCA-icon.png
│ ├── BounCA.pdf
│ └── BounCA.sketch
├── logs
└── .gitignore
├── make-docs.sh
├── make-package.sh
├── manage.py
├── pyproject.toml
├── requirements.docs.txt
├── requirements.txt
├── run-checks-node.sh
├── run-checks-python.sh
├── run-checks.sh
├── run-dev-server.sh
├── run-tests.sh
├── setup.cfg
├── setup.py
├── superuser_signup
├── __init__.py
├── apps.py
├── forms.py
├── templates
│ └── account
│ │ └── signup.html
└── views.py
├── vuetifyforms
├── README.md
├── __init__.py
├── apps.py
├── components.py
├── management
│ └── commands
│ │ ├── __init__.py
│ │ └── generate_forms.py
├── templates
│ └── vuetify
│ │ ├── display_form.html
│ │ ├── field.html
│ │ ├── layout
│ │ ├── baseinput.html
│ │ ├── buttonholder.html
│ │ ├── column.html
│ │ ├── fieldset.html
│ │ ├── flex.html
│ │ ├── row.html
│ │ └── spacer.html
│ │ ├── script
│ │ ├── default.js
│ │ ├── imports.js
│ │ └── methods.js
│ │ ├── uni_form.html
│ │ └── whole_uni_form.html
├── templatetags
│ ├── __init__.py
│ └── crispy_forms_vuetify.py
├── views.py
└── vue.py
└── x509_pki
├── __init__.py
├── admin.py
├── apps.py
├── management
├── __init__.py
└── commands
│ └── __init__.py
├── migrations
├── 0001_squashed_0015_keystore_p12.py
├── 0002_keystore_fingerprint.py
├── 0003_alter_keystore_fingerprint.py
├── 0004_alter_certificate_type.py
├── 0005_alter_certificate_crl_distribution_url.py
├── 0006_keystore_p12_legacy.py
└── __init__.py
├── models.py
└── tests
├── __init__.py
├── factories.py
├── test_factories.py
└── test_models.py
/.codacy.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | eslint:
3 | enabled: true
4 | fixme:
5 | enabled: true
6 | duplication:
7 | enabled: true
8 | config:
9 | languages:
10 | - python
11 | - javascript
12 | pep8:
13 | enabled: true
14 | radon:
15 | enabled: true
16 | ratings:
17 | paths:
18 | - "**.py"
19 | exclude_paths:
20 | - '**/migrations/**'
21 | - '**/tests/**'
22 | - 'ci/*'
23 | - 'docs/*'
24 | - 'etc/*'
25 | - 'graphics/*'
26 | - 'media/*'
27 | - 'pki/*'
28 | - 'bounca/static/**'
29 | - 'bounca/webapp/static/**'
30 |
--------------------------------------------------------------------------------
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | engines:
2 | eslint:
3 | enabled: true
4 | fixme:
5 | enabled: true
6 | duplication:
7 | enabled: true
8 | config:
9 | languages:
10 | - python
11 | #mass_threshold: 30
12 | - javascript
13 | pep8:
14 | enabled: true
15 | radon:
16 | enabled: true
17 | ratings:
18 | paths:
19 | - "**.py"
20 | exclude_paths:
21 | - '**/migrations/**/*'
22 | - '**/tests/**/*'
23 | - 'ci/*'
24 | - 'docs/*'
25 | - 'etc/*'
26 | - 'graphics/*'
27 | - 'media/*'
28 | - 'pki/*'
29 | - 'bounca/static/*'
30 |
--------------------------------------------------------------------------------
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | source = .
3 | omit =
4 | bounca/management/*
5 | bounca/management/commands/*
6 | bounca/migrations/*
7 | **/__init__.py
8 | manage*
9 | */test*
10 | bounca/wsgi.py
11 | env/*
12 | venv/*
13 | [html]
14 | title = Coverage Report for BounCA
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 4
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
15 | [gulpfile.babel.js]
16 | indent_style = space
17 | indent_size = 2
18 |
19 | [*.{yaml,yml}]
20 | indent_size = 2
21 |
22 | [*.eslintrc]
23 | indent_size = 2
24 |
25 | [*.vue]
26 | indent_size = 2
27 | tab_width = 2
28 | ij_continuation_indent_size = 2
29 | ij_vue_indent_children_of_top_level = template
30 | ij_vue_interpolation_new_line_after_start_delimiter = true
31 | ij_vue_interpolation_new_line_before_end_delimiter = true
32 | ij_vue_interpolation_wrap = off
33 | ij_vue_keep_indents_on_empty_lines = false
34 | ij_vue_spaces_within_interpolation_expressions = true
35 | ij_vue_uniform_indent = true
36 |
37 | [Makefile]
38 | indent_style = tab
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 | *.pyc
6 | *.swp
7 | *.DS_Store
8 | **/doc/_build
9 | .mypy_cache
10 | node_modules
11 | package-lock.json
12 |
13 | # log files
14 | npm-debug.log*
15 | yarn-debug.log*
16 | yarn-error.log*
17 | pnpm-debug.log*
18 | *.log
19 |
20 | # C extensions
21 | *.so
22 |
23 | # Distribution / packaging
24 | out/
25 | .Python
26 | env/
27 | build/
28 | develop-eggs/
29 | downloads/
30 | eggs/
31 | .eggs/
32 | lib/
33 | libs/
34 | lib64/
35 | parts/
36 | sdist/
37 | var/
38 | nginx/
39 |
40 | #bounca/static/libs/
41 | *.egg-info/
42 | .installed.cfg
43 | *.egg
44 |
45 | # PyInstaller
46 | # Usually these files are written by a python script from a template
47 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
48 | *.manifest
49 | *.spec
50 |
51 | # Installer logs
52 | pip-log.txt
53 | pip-delete-this-directory.txt
54 |
55 | # Unit test / coverage reports
56 | htmlcov/
57 | .tox/
58 | .coverage
59 | coverage.xml
60 | .coverage.*
61 | .cache
62 | nosetests.xml
63 | *,cover
64 | .hypothesis/
65 |
66 | # Translations
67 | *.mo
68 | *.pot
69 |
70 | # Sphinx documentation
71 | docs/_build/
72 |
73 | # PyBuilder
74 | target/
75 |
76 | #Ipython Notebook
77 | .ipynb_checkpoints
78 |
79 | # IDE
80 | .project
81 | .pydevproject
82 | .idea
83 | .settings
84 | .vscode
85 | *.suo
86 | *.ntvs*
87 | *.njsproj
88 | *.sln
89 | *.sw?
90 |
91 | # Other
92 | tmp/
93 | pki/
94 | etc/bounca/services.yaml
95 | TODO
96 |
97 | # Static
98 | media/static
99 |
100 | #frontend
101 | front/node_modules
102 | front/dist
103 |
104 | # local env files
105 | .env.local
106 | .env.*.local
107 |
108 |
109 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # Welcome to BounCA - Personal Key Management
6 |
7 | ## Contributing
8 |
9 |
10 | ## Bug Reports & Feature Requests
11 |
12 | Please use the [issue tracker](https://gitlab.com/bounca/bounca/-/issues) to report any bugs or file feature requests.
13 |
14 | ## Contributing
15 |
16 | 1. Create an issue and describe your idea
17 | 2. Create your feature branch (`git checkout -b my-new-feature`)
18 | 3. Commit your changes (`git commit -am 'Add some feature'`)
19 | 4. Publish the branch (`git push origin my-new-feature`)
20 | 5. Create a new Pull Request
21 | 6. Thanks!
22 |
23 | ## License
24 |
25 | Apache License v2 - (c) 2016-2022, Repleo, Amstelveen
26 |
27 | ## Author Information
28 |
29 | Jeroen Arnoldus (jeroen@repleo.nl)
30 |
31 | [Repleo](https://www.repleo.nl), Amsterdam, Holland -- www.repleo.nl
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | PYTHON_FOLDERS = api bounca certificate_engine vuetifyforms x509_pki superuser_signup
2 | LOCAL_SERVER_PORT ?= 8000
3 |
4 | default:
5 | @echo "No default target!"
6 |
7 | frontend_collect:
8 | python manage.py collectstatic --link --noinput
9 |
10 | runserver:
11 | python manage.py runserver 0.0.0.0:$(LOCAL_SERVER_PORT)
12 |
13 | quality: flake8 black_check isort_check
14 |
15 | isort_check:
16 | find $(PYTHON_FOLDERS) -path '**/migrations' -prune -o -name '*.py' -print | xargs isort -c
17 |
18 | isort_fix:
19 | find $(PYTHON_FOLDERS) -path '**/migrations' -prune -o -name '*.py' -print | xargs isort
20 |
21 | flake8:
22 | flake8 $(PYTHON_FOLDERS)
23 |
24 | black_fix:
25 | black .
26 |
27 | black_check:
28 | black --check .
29 |
30 | website:
31 | $(MAKE) -C ./docs html
32 |
33 | runwebsiteserver:
34 | python3 -m http.server -d ./docs/build/html 8090
35 |
36 | createvueforms:
37 | python3 manage.py generate_forms
38 |
39 | docserver:
40 | python3 -m http.server --directory ./docs/build/html 8090
41 |
42 | update-python-packages:
43 | pur
44 |
45 | migrate:
46 | python manage.py migrate
47 |
--------------------------------------------------------------------------------
/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/__init__.py
--------------------------------------------------------------------------------
/api/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django.forms import BooleanField, ModelForm
3 |
4 | from . import utils
5 | from .models import AuthorisedApp
6 |
7 |
8 | class AuthorisedAppForm(ModelForm):
9 | generate_new_token = BooleanField(required=False, initial=False)
10 |
11 | class Meta:
12 | model = AuthorisedApp
13 | fields = "__all__"
14 |
15 | def __init__(self, *args, **kwargs):
16 | super(AuthorisedAppForm, self).__init__(*args, **kwargs)
17 | self.fields["token"].disabled = not self.current_user.is_superuser
18 | self.fields["token"].required = False
19 |
20 | def clean(self):
21 | if self.cleaned_data.get("generate_new_token", False):
22 | self.cleaned_data["token"] = utils.new_token(44)
23 | return self.cleaned_data
24 |
25 | def save(self, commit=True):
26 | obj = super(AuthorisedAppForm, self).save(commit=False)
27 | obj.save(commit)
28 | if commit:
29 | obj.save()
30 | obj.save_m2m()
31 | return obj
32 |
33 |
34 | @admin.register(AuthorisedApp)
35 | class AppAdmin(admin.ModelAdmin):
36 | form = AuthorisedAppForm
37 | list_display = ("name", "token")
38 |
39 | def get_form(self, request, obj=None, **kwargs):
40 | form = super(AppAdmin, self).get_form(request, obj, **kwargs)
41 | form.current_user = request.user
42 | return form
43 |
--------------------------------------------------------------------------------
/api/apps.py:
--------------------------------------------------------------------------------
1 | """Api name"""
2 |
3 | from django.apps import AppConfig
4 |
5 |
6 | class ApiConfig(AppConfig):
7 | name = "api"
8 |
--------------------------------------------------------------------------------
/api/auth/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/auth/__init__.py
--------------------------------------------------------------------------------
/api/auth/adapter.py:
--------------------------------------------------------------------------------
1 | from allauth.account.adapter import DefaultAccountAdapter
2 | from allauth.utils import build_absolute_uri
3 | from rest_framework.reverse import reverse
4 |
5 |
6 | class DefaultAccountAdapterFrontendHost(DefaultAccountAdapter):
7 | def get_email_confirmation_url(self, request, emailconfirmation):
8 | """Constructs the email confirmation (activation) url.
9 |
10 | Note that if you have architected your system such that email
11 | confirmations are sent outside of the request context `request`
12 | can be `None` here.
13 | """
14 | url = reverse("account_confirm_email", args=[emailconfirmation.key])
15 | ret = build_absolute_uri(None, url)
16 | return ret
17 |
--------------------------------------------------------------------------------
/api/auth/serializers.py:
--------------------------------------------------------------------------------
1 | from dj_rest_auth.serializers import PasswordResetSerializer
2 | from django.conf import settings
3 |
4 |
5 | class PasswordResetSerializerFrontendHost(PasswordResetSerializer):
6 | """
7 | Serializer for requesting a password reset e-mail.
8 | """
9 |
10 | def save(self):
11 | if "allauth" in settings.INSTALLED_APPS:
12 | from allauth.account.forms import default_token_generator
13 | else:
14 | from django.contrib.auth.tokens import default_token_generator
15 |
16 | request = self.context.get("request")
17 | # Set some values to trigger the send_email method.
18 | opts = {
19 | "use_https": request.is_secure(),
20 | "from_email": getattr(settings, "DEFAULT_FROM_EMAIL"),
21 | "request": None, # None triggers to use the host from site object
22 | "token_generator": default_token_generator,
23 | }
24 |
25 | opts.update(self.get_email_options())
26 | self.reset_form.save(**opts)
27 |
--------------------------------------------------------------------------------
/api/authentication.py:
--------------------------------------------------------------------------------
1 | from functools import wraps
2 |
3 | from django.core.cache import cache
4 | from rest_framework.authentication import BaseAuthentication
5 |
6 | from api.models import AuthorisedApp
7 |
8 | KEYS_TTL = 1800
9 |
10 |
11 | def cache_value(func):
12 | @wraps(func)
13 | def new_func(self, app_token, *args, **kwargs):
14 | key = f":app_auth:authorised_app:{app_token}:"
15 | data = cache.get(key)
16 | if data is None:
17 | data = func(self, app_token, *args, **kwargs)
18 | cache.set(key, data, KEYS_TTL)
19 |
20 | return data
21 |
22 | return new_func
23 |
24 |
25 | class AppTokenAuthentication(BaseAuthentication):
26 | def authenticate(self, request):
27 | # The tokens to set: X-AUTH-TOKEN or X-USER-AUTH-TOKEN
28 | app_token = request.META.get("HTTP_X_AUTH_TOKEN")
29 | user_token = request.META.get("HTTP_X_USER_AUTH_TOKEN")
30 | app = self.authorised_app_for_token(app_token)
31 | if app:
32 | return app.user, AuthData(app_token, user_token)
33 | else:
34 | return None
35 |
36 | # @cache_value
37 | def authorised_app_for_token(self, app_token):
38 | return AuthorisedApp.objects.filter(token=app_token).first()
39 |
40 |
41 | class AuthData(object):
42 | """
43 | We store important data connected to the authorisation step in
44 | this object and we store this object to the request object so
45 | that the data here can be used through the view and related classes.
46 | """
47 |
48 | def __init__(self, app_token, user_token):
49 | self.app_token = app_token
50 | self.user_token = user_token
51 |
--------------------------------------------------------------------------------
/api/filters.py:
--------------------------------------------------------------------------------
1 | from typing import List, Optional, Tuple
2 |
3 | from django.db import models
4 | from rest_framework import filters
5 |
6 | # Code fragment from https://github.com/encode/django-rest-framework/issues/1005
7 |
8 |
9 | class RelatedOrderingFilter(filters.OrderingFilter):
10 | _max_related_depth = 3
11 |
12 | @staticmethod
13 | def _get_verbose_name(field: models.Field, non_verbose_name: str) -> str:
14 | return str(field.verbose_name) if hasattr(field, "verbose_name") else non_verbose_name.replace("_", " ")
15 |
16 | def _retrieve_all_related_fields(
17 | self, fields: Tuple[models.Field], model: models.Model, depth: int = 0
18 | ) -> List[Tuple[str, str]]:
19 | valid_fields: List[Tuple[str, str]] = []
20 | if depth > self._max_related_depth:
21 | return valid_fields
22 | for field in fields:
23 | if field.related_model and field.related_model != model:
24 | rel_fields = self._retrieve_all_related_fields(
25 | field.related_model._meta.get_fields(), field.related_model, depth + 1
26 | )
27 | for rel_field in rel_fields:
28 | valid_fields.append((f"{field.name}__{rel_field[0]}", self._get_verbose_name(field, rel_field[1])))
29 | else:
30 | valid_fields.append(
31 | (
32 | field.name,
33 | self._get_verbose_name(field, field.name),
34 | )
35 | )
36 | return valid_fields
37 |
38 | def get_valid_fields(
39 | self, queryset: models.QuerySet, view, context: Optional[dict] = None
40 | ) -> List[Tuple[str, str]]:
41 | ordering_fields = getattr(view, "ordering_fields", self.ordering_fields)
42 | valid_fields: List[Tuple[str, str]]
43 | if not ordering_fields == "__all_related__":
44 | if not context:
45 | context = {}
46 | valid_fields = super().get_valid_fields(queryset, view, context)
47 | else:
48 | valid_fields = [
49 | *self._retrieve_all_related_fields(queryset.model._meta.get_fields(), queryset.model),
50 | *[(key, key.title().split("__")) for key in queryset.query.annotations],
51 | ]
52 | return valid_fields
53 |
--------------------------------------------------------------------------------
/api/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-05-26 20:35
2 |
3 | import django.db.models.deletion
4 | from django.conf import settings
5 | from django.db import migrations, models
6 |
7 |
8 | class Migration(migrations.Migration):
9 |
10 | initial = True
11 |
12 | dependencies = [
13 | ('x509_pki', '0004_alter_certificate_type'),
14 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15 | ]
16 |
17 | operations = [
18 | migrations.CreateModel(
19 | name='Scope',
20 | fields=[
21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22 | ('access', models.CharField(choices=[('RCRL', 'Read CRL of root and intermediate certificates'), ('RCERT', 'Read root and intermediate certificates'), ('RISSUED', 'Read issued certificates, including private key')], max_length=7)),
23 | ('certificate', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='x509_pki.certificate')),
24 | ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
25 | ],
26 | options={
27 | 'ordering': ['owner', 'certificate', 'access'],
28 | 'unique_together': {('owner', 'access', 'certificate')},
29 | },
30 | ),
31 | migrations.CreateModel(
32 | name='AuthorisedApp',
33 | fields=[
34 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
35 | ('name', models.TextField(unique=True)),
36 | ('token', models.TextField(unique=True)),
37 | ('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
38 | ('scopes', models.ManyToManyField(to='api.scope')),
39 | ],
40 | options={
41 | 'ordering': ['name'],
42 | },
43 | ),
44 | ]
45 |
--------------------------------------------------------------------------------
/api/migrations/0002_remove_authorisedapp_scopes_delete_scope.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-05-28 06:55
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('api', '0001_initial'),
10 | ]
11 |
12 | operations = [
13 | migrations.RemoveField(
14 | model_name='authorisedapp',
15 | name='scopes',
16 | ),
17 | migrations.DeleteModel(
18 | name='Scope',
19 | ),
20 | ]
21 |
--------------------------------------------------------------------------------
/api/migrations/0003_rename_owner_authorisedapp_user.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-05-28 06:58
2 |
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('api', '0002_remove_authorisedapp_scopes_delete_scope'),
10 | ]
11 |
12 | operations = [
13 | migrations.RenameField(
14 | model_name='authorisedapp',
15 | old_name='owner',
16 | new_name='user',
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/api/migrations/0004_alter_authorisedapp_name_and_more.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-06-18 22:28
2 |
3 | from django.conf import settings
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11 | ('api', '0003_rename_owner_authorisedapp_user'),
12 | ]
13 |
14 | operations = [
15 | migrations.AlterField(
16 | model_name='authorisedapp',
17 | name='name',
18 | field=models.TextField(),
19 | ),
20 | migrations.AlterUniqueTogether(
21 | name='authorisedapp',
22 | unique_together={('name', 'user')},
23 | ),
24 | ]
25 |
--------------------------------------------------------------------------------
/api/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/migrations/__init__.py
--------------------------------------------------------------------------------
/api/mixins.py:
--------------------------------------------------------------------------------
1 | """Create serializer validation errors from django validation errors for automatic handling"""
2 |
3 | from django.core.exceptions import ValidationError as DjangoValidationError
4 | from rest_framework import serializers
5 |
6 | from certificate_engine.ssl.certificate import PolicyError
7 |
8 |
9 | class TrapDjangoValidationErrorCreateMixin(object):
10 | def perform_create(self, serializer):
11 | try:
12 | serializer.save()
13 | except DjangoValidationError as detail:
14 | raise serializers.ValidationError({"non_field_errors": detail.messages})
15 | except PolicyError as detail:
16 | raise serializers.ValidationError(detail.args[0])
17 |
18 |
19 | class TrapDjangoValidationErrorUpdateMixin(object):
20 | def perform_update(self, serializer):
21 | try:
22 | serializer.save()
23 | except DjangoValidationError as detail:
24 | raise serializers.ValidationError({"non_field_errors": detail.messages})
25 | except PolicyError as detail:
26 | raise serializers.ValidationError(detail.args[0])
27 |
--------------------------------------------------------------------------------
/api/models.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import User
2 | from django.db import models
3 |
4 | from api import utils
5 |
6 |
7 | class AuthorisedApp(models.Model):
8 | name = models.TextField()
9 | token = models.TextField(unique=True)
10 | user = models.ForeignKey(User, on_delete=models.PROTECT)
11 |
12 | class Meta:
13 | ordering = ["name"]
14 | unique_together = ("name", "user")
15 |
16 | def save(self, *args, **kwargs):
17 | if not self.id:
18 | self.token = utils.new_token(44)
19 | super(AuthorisedApp, self).save(*args, **kwargs)
20 |
21 | def __str__(self):
22 | return "{} - {}".format(self.name, self.token)
23 |
--------------------------------------------------------------------------------
/api/permissions.py:
--------------------------------------------------------------------------------
1 | """Permission classes for retrieving certificates"""
2 |
3 | from rest_framework import permissions
4 |
5 |
6 | class BounCAUserPermissions(permissions.BasePermission):
7 | def has_permission(self, request, view):
8 | if view.action == "list":
9 | return request.user.is_admin
10 | elif view.action == "retrieve":
11 | return True
12 | else:
13 | return False
14 |
15 | def has_object_permission(self, request, view, obj):
16 | if view.action == "retrieve":
17 | return request.user.is_admin or obj == request.user
18 | else:
19 | return False
20 |
--------------------------------------------------------------------------------
/api/templates/rest_framework/api.html:
--------------------------------------------------------------------------------
1 | {% extends "rest_framework/base.html" %}
2 |
3 |
4 | {% block title %}BounCA API{% endblock %}
5 |
6 | {% block branding %}
7 | BounCA API
8 |
9 | Admin
10 |
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/api/templates/rest_framework/login.html:
--------------------------------------------------------------------------------
1 | {% extends "rest_framework/login_base.html" %}
2 |
3 | {% block branding %}
4 |
BounCA API
5 | {% endblock %}
6 |
--------------------------------------------------------------------------------
/api/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/tests/__init__.py
--------------------------------------------------------------------------------
/api/tests/api/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/tests/api/__init__.py
--------------------------------------------------------------------------------
/api/tests/api/auth/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/tests/api/auth/__init__.py
--------------------------------------------------------------------------------
/api/tests/api/auth/test_auth.py:
--------------------------------------------------------------------------------
1 | from rest_framework import status
2 | from rest_framework.test import APIClient, APITestCase
3 |
4 |
5 | class AuthRegistrationTest(APITestCase):
6 | """
7 | Test retrieve and creating tokens
8 | """
9 |
10 | base_url = "/api/v1/reqistration"
11 |
12 | def test_account_email_verification_sent_not_found(self):
13 | client = APIClient()
14 | response = client.get(f"{self.base_url}/account-email-verification-sent/", format="json")
15 | self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
16 |
--------------------------------------------------------------------------------
/api/tests/api/tokens/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/tests/api/tokens/__init__.py
--------------------------------------------------------------------------------
/api/tests/base.py:
--------------------------------------------------------------------------------
1 | from rest_framework.test import APITestCase
2 |
3 | from api.tests.factories import AuthorisedAppFactory
4 |
5 |
6 | class APITokenLoginTestCase(APITestCase):
7 | """
8 | APITestCase that uses our AuthorisedApp model token to login.
9 | """
10 |
11 | @classmethod
12 | def setUpTestData(cls):
13 | cls.auth_app = AuthorisedAppFactory()
14 |
15 | def setUp(self):
16 | self.client.credentials(HTTP_X_AUTH_TOKEN=self.auth_app.token)
17 |
18 |
19 | class APILoginTestCase(APITestCase):
20 | """
21 | APITestCase that uses credentials to login.
22 | """
23 |
24 | @classmethod
25 | def setUpTestData(cls):
26 | cls.auth_app = AuthorisedAppFactory()
27 | cls.user = cls.auth_app.user
28 |
29 | def setUp(self):
30 | self.client.login(username=self.user.username, password="password123")
31 |
--------------------------------------------------------------------------------
/api/tests/factories.py:
--------------------------------------------------------------------------------
1 | import factory
2 | from django.core.exceptions import ObjectDoesNotExist
3 | from factory.django import DjangoModelFactory
4 | from faker import Factory as FakerFactory
5 |
6 | from api import models, utils
7 | from x509_pki.tests.factories import UserFactory
8 |
9 | fake = FakerFactory.create()
10 |
11 |
12 | class AuthorisedAppFactory(DjangoModelFactory):
13 | class Meta:
14 | model = models.AuthorisedApp
15 |
16 | name = fake.sentence(nb_words=6, variable_nb_words=True)
17 | token = factory.LazyFunction(utils.new_token)
18 | user = factory.LazyFunction(UserFactory.default)
19 |
20 | @classmethod
21 | def default(cls):
22 | try:
23 | authorised_app = models.AuthorisedApp.objects.get(token="aasdfghjkl")
24 | except ObjectDoesNotExist:
25 | authorised_app = AuthorisedAppFactory.create(token="aasdfghjkl")
26 | return authorised_app
27 |
--------------------------------------------------------------------------------
/api/tests/test_factories.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | from __future__ import absolute_import, unicode_literals
3 |
4 | from django.test import TestCase
5 |
6 | from api.tests.factories import AuthorisedAppFactory
7 |
8 |
9 | class FactoriesTest(TestCase):
10 | """
11 | Very simple tests to ensure the factories work as expected.
12 | """
13 |
14 | def test_authorised_app_factory(self):
15 | authorised_app = AuthorisedAppFactory()
16 | self.assertTrue(authorised_app.id is not None)
17 | self.assertTrue(len(authorised_app.name) > 1)
18 | self.assertTrue(authorised_app.user is not None)
19 | # Base64 encoding of 16 bit random number
20 | self.assertTrue(len(authorised_app.token) == 44)
21 |
--------------------------------------------------------------------------------
/api/tokens/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/api/tokens/__init__.py
--------------------------------------------------------------------------------
/api/tokens/serializers.py:
--------------------------------------------------------------------------------
1 | from rest_framework.serializers import ModelSerializer
2 |
3 | from api.models import AuthorisedApp
4 |
5 |
6 | class AuthorisedAppSerializer(ModelSerializer):
7 | # TODO it is ugly that "user" is visible in the Options of the API.
8 | # But not having it as field, will fail the serializer
9 | # Solution provided in
10 | # https://www.django-rest-framework.org/tutori
11 | # al/4-authentication-and-permissions/#associating-snippets-with-users
12 | # will not work, as we have a unique constraint for user/name.
13 | class Meta:
14 | fields = ("id", "name", "token", "user")
15 | read_only_fields = ("token",)
16 | model = AuthorisedApp
17 | extra_kwargs = {"user": {"required": False}}
18 |
--------------------------------------------------------------------------------
/api/tokens/urls.py:
--------------------------------------------------------------------------------
1 | from rest_framework.routers import DefaultRouter
2 |
3 | from api.tokens.views import AuthorisedAppViewSet
4 |
5 | router = DefaultRouter()
6 | router.register(r"tokens", AuthorisedAppViewSet, basename="token")
7 | urlpatterns = router.urls
8 |
--------------------------------------------------------------------------------
/api/tokens/views.py:
--------------------------------------------------------------------------------
1 | from copy import deepcopy
2 |
3 | from rest_framework import mixins, status
4 | from rest_framework.permissions import IsAuthenticated
5 | from rest_framework.response import Response
6 | from rest_framework.viewsets import GenericViewSet
7 |
8 | from api.models import AuthorisedApp
9 | from api.tokens.serializers import AuthorisedAppSerializer
10 | from api.views import APIPageNumberPagination
11 |
12 |
13 | class AuthorisedAppViewSet(
14 | mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet
15 | ):
16 | """
17 | A ViewSet for retrieving tokens.
18 | """
19 |
20 | serializer_class = AuthorisedAppSerializer
21 | pagination_class = APIPageNumberPagination
22 | permission_classes = [
23 | IsAuthenticated,
24 | ]
25 |
26 | def get_queryset(self):
27 | return AuthorisedApp.objects.filter(user=self.request.user)
28 |
29 | def create(self, request, *args, **kwargs):
30 | data = deepcopy(request.data)
31 | data["user"] = self.request.user.id
32 | serializer = self.get_serializer(data=data)
33 |
34 | serializer.is_valid(raise_exception=True)
35 | self.perform_create(serializer)
36 | headers = self.get_success_headers(serializer.data)
37 | return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
38 |
--------------------------------------------------------------------------------
/api/urls.py:
--------------------------------------------------------------------------------
1 | """API v1 end-points"""
2 | from dj_rest_auth.registration.urls import urlpatterns as urlpatterns_registration
3 | from dj_rest_auth.urls import urlpatterns as urlpatterns_rest_auth
4 | from django.conf.urls import include
5 | from django.urls import path
6 | from rest_framework_swagger.views import get_swagger_view
7 |
8 | from api.tokens.urls import urlpatterns as urlpatterns_token
9 |
10 | from .views import (
11 | ApiRoot,
12 | CertificateCRLFilesView,
13 | CertificateFilesView,
14 | CertificateInfoView,
15 | CertificateInstanceView,
16 | CertificateListView,
17 | CertificateRenewView,
18 | NotFoundView,
19 | )
20 |
21 |
22 | class CertificateCrlFileView:
23 | pass
24 |
25 |
26 | urlpatterns_apiv1 = [
27 | path("certificates/files/", CertificateFilesView.as_view(), name="certificate-files"),
28 | path("certificates//download", CertificateFilesView.as_view(), name="certificate-download"),
29 | path("certificates//crl", CertificateCRLFilesView.as_view(), name="certificate-crl"),
30 | path("certificates//info", CertificateInfoView.as_view(), name="certificate-info"),
31 | path("certificates//renew", CertificateRenewView.as_view(), name="certificate-renew"),
32 | path("certificates/", CertificateInstanceView.as_view(), name="certificate-instance"),
33 | path("certificates", CertificateListView.as_view(), name="certificates"),
34 | path("auth/", include(urlpatterns_token)),
35 | path("auth/", include(urlpatterns_rest_auth)),
36 | path(
37 | "auth/registration/account-email-verification-sent/",
38 | NotFoundView.as_view(),
39 | name="account_email_verification_sent",
40 | ),
41 | path("auth/registration/", include(urlpatterns_registration)),
42 | ]
43 |
44 | schema_view = get_swagger_view(title="BounCA API")
45 |
46 |
47 | urlpatterns = [
48 | path("v1/", include(urlpatterns_apiv1)),
49 | path("", ApiRoot.as_view(urlpatterns_apiv1), name="api-root"),
50 | ]
51 |
--------------------------------------------------------------------------------
/api/utils.py:
--------------------------------------------------------------------------------
1 | import random
2 | import string
3 |
4 |
5 | def new_token(length=44):
6 | r = random.SystemRandom()
7 | return "".join(r.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for i in range(length))
8 |
--------------------------------------------------------------------------------
/bounca/__init__.py:
--------------------------------------------------------------------------------
1 | from django.utils.version import get_version
2 |
3 | # version types: final, 'alpha', 'beta', 'rc'
4 |
5 | VERSION = (0, 2, 0, "alpha", 0)
6 |
7 | __version__ = get_version(VERSION)
8 |
--------------------------------------------------------------------------------
/bounca/management/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/bounca/management/__init__.py
--------------------------------------------------------------------------------
/bounca/management/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/bounca/management/commands/__init__.py
--------------------------------------------------------------------------------
/bounca/management/commands/site.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.contrib.sites.models import Site
3 | from django.core.management.base import BaseCommand
4 |
5 |
6 | class Command(BaseCommand):
7 | help = "Creating Site object"
8 |
9 | def add_arguments(self, parser):
10 | parser.add_argument("host", help="Base host URI of frontend")
11 |
12 | def handle(self, *args, **options):
13 | print(f"Setting site Frontend URI to: {options['host']}")
14 | if Site.objects.filter(pk=getattr(settings, "SITE_ID", 1)).exists():
15 | site = Site.objects.get(pk=getattr(settings, "SITE_ID", 1))
16 | site.domain = options["host"]
17 | site.name = getattr(settings, "SITE_NAME", "Bounca PKI")
18 | site.save()
19 | else:
20 | Site(
21 | pk=getattr(settings, "SITE_ID", 1),
22 | domain=options["host"],
23 | name=getattr(settings, "SITE_NAME", "Bounca PKI"),
24 | ).save()
25 |
--------------------------------------------------------------------------------
/bounca/urls.py:
--------------------------------------------------------------------------------
1 | """Main URL config"""
2 | from dj_rest_auth.registration.views import VerifyEmailView
3 | from django.conf import settings
4 | from django.conf.urls import include
5 | from django.contrib import admin
6 | from django.contrib.staticfiles.urls import staticfiles_urlpatterns
7 | from django.urls import path
8 | from django.views.generic import RedirectView, TemplateView
9 |
10 | from api.urls import urlpatterns as urlpatterns_api
11 | from superuser_signup.views import CreateSuperUserView
12 |
13 | urlpatterns = [
14 | # these urls are used to generate email content
15 | path("auth/password-reset/confirm//", TemplateView.as_view(), name="password_reset_confirm"),
16 | path("auth/login/", VerifyEmailView.as_view(), name="account_email_verification_sent"),
17 | path("api/", include(urlpatterns_api)),
18 | path("auth-api/", include("rest_framework.urls")),
19 | path("auth/account-confirm-email/", TemplateView.as_view(), name="account_confirm_email"),
20 | ]
21 |
22 | if settings.ADMIN:
23 | urlpatterns += [
24 | path("admin/", admin.site.urls),
25 | path("grappelli/", include("grappelli.urls")), # grappelli URLS
26 | ]
27 | if settings.SUPERUSER_SIGNUP:
28 | urlpatterns += [
29 | # Other URL patterns ...
30 | path("accounts/signup/", CreateSuperUserView.as_view(), name="superuser_signup"),
31 | path("accounts/login/", RedirectView.as_view(url="/admin/login"), name="account_login")
32 | # More URL patterns ...
33 | ]
34 |
35 |
36 | urlpatterns += staticfiles_urlpatterns()
37 |
--------------------------------------------------------------------------------
/bounca/wsgi.py:
--------------------------------------------------------------------------------
1 | """uWSGI config"""
2 |
3 | import os
4 |
5 | from django.core.wsgi import get_wsgi_application
6 |
7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bounca.settings")
8 |
9 | application = get_wsgi_application()
10 |
--------------------------------------------------------------------------------
/build-front.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -ex
2 |
3 | BASEDIR=$(dirname "$0")
4 | VERSION=$(awk '{ sub(/.*\//, ""); print }' <<< "$CI_COMMIT_REF_NAME")
5 |
6 | if [[ $VERSION =~ ^([0-9]\.?)+$ ]]; then
7 | echo ""
8 | else
9 | VERSION="0.0.0-dev"
10 | fi
11 |
12 | echo $VERSION
13 |
14 | cd front
15 |
16 | sed -ri "s|\"version\":\ \"0.0.0-dev\"|\"version\":\ \"$VERSION\"|g" package.json
17 |
18 | # npm modules are already fetched
19 | # npm install --legacy-peer-deps
20 | # When facing error:0308010C:digital envelope routines::unsupported add this export
21 | export NODE_OPTIONS=--openssl-legacy-provider
22 | npm run build --production
23 |
24 |
--------------------------------------------------------------------------------
/build-package.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -ex
2 |
3 |
4 | BASEDIR=$(dirname "$0")
5 |
6 | cd front
7 | rm -rf node_modules public src
8 | rm .babelrc .env .env.production .eslintignore .eslintrc.js .postcssrc.js
9 | rm Makefile README.md babel.config.js package.json vue.config.js
10 |
11 | cd ..
12 |
13 | mkdir -p out/bounca/
14 | mv api out/bounca/
15 | mv superuser_signup out/bounca/
16 | mv bounca out/bounca/
17 | mv certificate_engine out/bounca/
18 | mv vuetifyforms out/bounca/
19 | mv etc out/bounca/
20 | mv front out/bounca/
21 | mv logs out/bounca/
22 | mv x509_pki out/bounca/
23 | mv manage.py out/bounca/
24 | mv CONTRIBUTING.md out/bounca/
25 | mv LICENSE out/bounca/
26 | mv README.md out/bounca/
27 | mv changelog.md out/bounca/
28 | mv requirements.txt out/bounca/
29 |
30 | tar -czvf "bounca.tar.gz" --owner=0 --group=0 -C out .
31 |
--------------------------------------------------------------------------------
/certificate_engine/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/certificate_engine/__init__.py
--------------------------------------------------------------------------------
/certificate_engine/apps.py:
--------------------------------------------------------------------------------
1 | """App name"""
2 |
3 | from django.apps import AppConfig
4 |
5 |
6 | class CertificateEngineConfig(AppConfig):
7 | name = "certificate_engine"
8 |
--------------------------------------------------------------------------------
/certificate_engine/ssl/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/certificate_engine/ssl/__init__.py
--------------------------------------------------------------------------------
/certificate_engine/ssl/info.py:
--------------------------------------------------------------------------------
1 | import os
2 | import subprocess
3 | import tempfile
4 |
5 |
6 | def get_certificate_info(crt: str) -> str:
7 | """
8 | Get Info of certificates
9 |
10 | Arguments: pem - string with certificate
11 | Returns: string
12 | """
13 | f = tempfile.NamedTemporaryFile(delete=False)
14 | path = f.name
15 | f.write(crt.encode("utf8"))
16 | f.close()
17 | cert_txt = subprocess.check_output(["openssl", "x509", "-text", "-noout", "-in", path])
18 | os.unlink(path)
19 | return cert_txt.decode("utf8")
20 |
21 |
22 | def get_certificate_fingerprint(crt: str) -> str:
23 | """
24 | Get Fingerprint of certificates
25 |
26 | Arguments: pem - string with certificate
27 | Returns: string
28 | """
29 | f = tempfile.NamedTemporaryFile(delete=False)
30 | path = f.name
31 | f.write(crt.encode("utf8"))
32 | f.close()
33 | cert_txt = subprocess.check_output(["openssl", "x509", "-fingerprint", "-sha1", "-noout", "-in", path])
34 | os.unlink(path)
35 | fingerprint = cert_txt.decode("utf8")
36 | return fingerprint.split("=")[1].strip()
37 |
--------------------------------------------------------------------------------
/certificate_engine/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/certificate_engine/tests/__init__.py
--------------------------------------------------------------------------------
/certificate_engine/tests/test_ed25519_key.py:
--------------------------------------------------------------------------------
1 | from cryptography.hazmat.primitives.asymmetric import ed25519
2 | from django.test import TestCase
3 |
4 | from certificate_engine.ssl.key import Key
5 |
6 |
7 | class KeyEd25519Test(TestCase):
8 | def test_generate_private_key(self):
9 | keyhandler = Key()
10 | keyhandler.create_key("ed25519", None)
11 | data = b"testdata"
12 | signature = keyhandler.key.sign(data)
13 | pkey = keyhandler.key.public_key()
14 | self.assertIsNotNone(pkey)
15 | # would throw InvalidSignature if not correct
16 | pkey.verify(signature, data)
17 | self.assertIsNotNone(keyhandler.key)
18 |
19 | def test_serialize_keys_passphrase(self):
20 | key = Key()
21 | key.create_key("ed25519", None)
22 | pem = key.serialize("test_store_keys_passphrase")
23 | prvkey = key.load(pem, "test_store_keys_passphrase")
24 | self.assertIsInstance(prvkey.key, ed25519.Ed25519PrivateKey)
25 |
26 | def test_store_keys_no_object(self):
27 | key = Key()
28 | with self.assertRaisesMessage(RuntimeError, "No key object"):
29 | key.serialize("test_store_keys_passphrase")
30 |
31 | def test_store_keys_no_passphrase(self):
32 | key = Key()
33 | key.create_key("ed25519", None)
34 | pem = key.serialize()
35 | key = Key()
36 | prvkey = key.load(pem)
37 | self.assertIsInstance(prvkey.key, ed25519.Ed25519PrivateKey)
38 |
39 | def test_store_keys_wrong_passphrase(self):
40 | key = Key()
41 | key.create_key("ed25519", None)
42 | pem = key.serialize("test_store_keys_wrong_passphrase")
43 | with self.assertRaisesMessage(ValueError, "Bad decrypt. Incorrect password?"):
44 | key.load(pem, "test_store_keys_passphrase")
45 |
46 | def test_check_passphrase_valid(self):
47 | key = Key()
48 | key.create_key("ed25519", None)
49 | pem = key.serialize("check_passphrase")
50 | self.assertTrue(key.check_passphrase(pem, "check_passphrase"))
51 |
52 | def test_check_passphrase_invalid(self):
53 | key = Key()
54 | key.create_key("ed25519", None)
55 | pem = key.serialize("test_check_passphrase_invalid")
56 | self.assertFalse(key.check_passphrase(pem, "check_passphrase"))
57 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | db:
4 | image: postgres:16
5 | environment:
6 | - POSTGRES_DB=bounca
7 | - POSTGRES_USER=bounca
8 | - POSTGRES_PASSWORD=fsRWF2k2k
9 | ports:
10 | - "5432:5432"
11 |
12 | nginx:
13 | image: nginx:1.16.0-alpine
14 | volumes:
15 | - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
16 | - ./nginx/certs/:/etc/nginx/certs/
17 | - ./nginx/www/:/var/www/
18 |
19 | ports:
20 | - "8443:443"
21 | - "8800:80"
22 | command: [nginx-debug, '-g', 'daemon off;']
23 |
24 |
25 |
--------------------------------------------------------------------------------
/docs/source/bounca/contribution.rst:
--------------------------------------------------------------------------------
1 | :header_title: Contribution
2 |
3 |
4 | Contribution
5 | ============
6 |
7 | Bug Reports & Feature Requests
8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 |
10 | Please use the `issue tracker`_ to report any bugs or file feature requests.
11 |
12 | Contributing
13 | ~~~~~~~~~~~~
14 |
15 | 1. Create an issue and describe your idea
16 | 2. Create your feature branch (`git checkout -b my-new-feature`)
17 | 3. Commit your changes (`git commit -am 'Add some feature'`)
18 | 4. Publish the branch (`git push origin my-new-feature`)
19 | 5. Create a new Pull Request
20 | 6. Thanks!
21 |
22 | License
23 | ~~~~~~~~~~~
24 |
25 | Apache License v2 - (c) 2016-2022, Repleo, Amstelveen
26 |
27 |
28 | Maintainers
29 | ~~~~~~~~~~~
30 | Jeroen Arnoldus (jeroen@repleo.nl)
31 |
32 | BounCA is written and maintained by `Repleo`_, Amsterdam, Holland.
33 |
34 | .. _issue tracker: https://gitlab.com/bounca/bounca/-/issues
35 | .. _Repleo: https://www.repleo.nl
36 |
--------------------------------------------------------------------------------
/docs/source/bounca/support.rst:
--------------------------------------------------------------------------------
1 | :header_title: Support
2 |
3 | Support
4 | =======
5 |
6 | Bugs & Support Issues
7 | ~~~~~~~~~~~~~~~~~~~~~
8 |
9 | You can file bug reports on our `GitLab issue tracker`_,
10 |
11 |
12 | Reporting Issues
13 | ~~~~~~~~~~~~~~~~
14 |
15 | When reporting a bug,
16 | please include as much information as possible that will help us solve this issue.
17 | This includes:
18 |
19 | * How to repeat
20 | * Action taken
21 | * Expected result
22 | * Actual result
23 |
24 |
25 | .. _GitLab Issue Tracker: https://gitlab.com/bounca/bounca/-/issues
26 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo1.client_cert/demo1.key:
--------------------------------------------------------------------------------
1 | -----BEGIN ENCRYPTED PRIVATE KEY-----
2 | MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIkYVqAhozPwwCAggA
3 | MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDW4f7NHvM5t2Zoo1blnBH2BIIE
4 | 0CZFeDrekk6HVxVWN6xL9ep1qmo8Bwv4omHq8nlIgyf8HZDnKr8jPJ8gs2BqOgzO
5 | YCZSJLPI34a+CHGwNIi9/iYiskotMZ2I88uCYY8SwJ3iVgHcU5RtISykCvleVkkP
6 | bMDzk9L42VHcTJL+APmzvlHPQcwDLGylLRL7RGhhW1clh/U1DTJZrHsJ+hmGJqho
7 | ltpzm2zuFQFFucRUpYNOhgDjXJLRmjvWL6kjqpKVn5wqtsfdPPQed22L+0eEaDFv
8 | y/klrVzmT5IG2aog7lHQt27a/txSC3GXCzxGykBpSHjqHWqDzu6WEkprJeyl1WDy
9 | CnMIE3oORFe47sUH80Zl50jFTltrqndWEC7Mm6JjuOOsHuvUv7S6Kg9+ZnfoMJRz
10 | gT0wFtYaCRrO4MWFEDrd38yJQoEtF5efUQ8fFbzY0NCWDUIooYCVPjTnWZloXdNZ
11 | NZt7eHTnSlH0IZ2lnel3Tu7947CfX8QnBZnA1EIMdqp0d9BM2pvIfH2jCoOsukCx
12 | NDjmNETLMoRt9lRdO2xesnDwo892A78iQVRGc8NgPmJODqFDcGU/PkD7Vnd2kjpK
13 | y/GmMzDt07RfNdpgzj1u3wz5mqMGY3g8AhNmPjPGvrxjasy/0x8CL8iG4mbN9waR
14 | hVQpQCPcCPkxab2lqTR6Wal80o/DgnHUFpc5ixopBmhOw0AsTde/l7gEOp8F/52s
15 | U0x5LbykwkR+K55AJYpNK3qTPnUayblq4qM1nGGlF3KHs2GDrJww/FSzMIW12Ybi
16 | lwUM9QN7a4mjzcvq3+WsQVvHFcYeK2ox0I7VVfs16pXiw950TWoHmBt7e5g/CpkR
17 | 1B+EeAoLBflL33BPmKfCH0zXXu3K3RsGPdeP7VLexuiXgA/8BD7xj3Z9d35fiQPj
18 | +sUSOSytYjOdDVO0NkhZBXr0Z2aN/+tbOaVfDELDHXPr6bq+GAe7wf7d/F4B72NQ
19 | dmiiUgfHJ5XGOpqSd/2Xs3htW5gsl3GH0SenfJYEMxgEgpXwCtPMW9nLgHJ4ZhdS
20 | U3MmNjQVTTp81tssv6kqklAdodIElnsKvO+4EbwOEArb1U2S0PNfBCv0UZPZnPo4
21 | kfBLHHyQsHL7fZ/TUsa+5LhcIOOi2ySW7mdWh0DCtxof5FaiWqglxpO+ynxEheVD
22 | ovJjO3VZxMIqkG5pd4Ayu/G4UPRAIi8lcT/qqH/FjoLwNg2vCs7ny9F18Uf6Tn8c
23 | 7ceoEq/LWGUCx1gB0KgRhrk0o9EC3irEDglVjz7chulldOGS/RupKR4s0taao9wA
24 | yV1/SEPPZsiaeVSqg92wVpL8y5JxHaGg7aZLpgRQ0/V3rMzi+PNBlxdATUhE4Y8g
25 | obsnkUBOd0vBjW+Pzj5SY4HRturLD3VNT0HDAREyP+W13oemHDCJz1z3lO900u37
26 | M2OYuRFKiOwVqH3NBO2Gc02ucO1t4kyH+v6HNxQgrpZCI4DsogcPBsvM+j4hvMCG
27 | F8DFimZzSUuagkvmTA4Jp2b/8xLH9d1BlxqHkPlGqhSVMP0FcwOHUZMTZY0xwrxJ
28 | oMcqZ9mXtQM0y8Y/D4b+YzAr87pRFwlWqva66hgQTK7kONKr56NuOtUSInwvqwpY
29 | Y8OczPVLnE2pFlc9LFWiGTEkHCRao4ckgkG7irbXdUPP
30 | -----END ENCRYPTED PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo1.client_cert/demo1.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/demo/nginx_client_auth/certs/demo1.client_cert/demo1.p12
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo1.client_cert/demo1.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
34 | 35xIEFcPq2a3ndt/KeLl4NKnNm7HEA==
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo1.client_cert/rootca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo2.client_cert/demo2.key:
--------------------------------------------------------------------------------
1 | -----BEGIN ENCRYPTED PRIVATE KEY-----
2 | MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIhXLwthICDtACAggA
3 | MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBAmLNwppVm4gJ+EwiKmgBo5BIIE
4 | 0JsK0lnl/3eT+bRbJPbJw40iEHlPLwRhqG3OS7eBw6Cs8G9WBOr/s8JjTks0CXNK
5 | rg1o7am20BtQ+EJXipGuQrJv6JPZ8iWytQwX47VBm0LRM/Oa2kvL6I3qJHN2SYGy
6 | 6aDxcPZHv9K60N964H0yU95CJ7P/e5Qw90BlItyOufYaV0uXWX7ylvJq0KbmYfeH
7 | 2m4ETvTkUVwhsDsLlwtCrZwdg5vVfZF3aHRJ0q1LYbn2aPlhBMj2zvt/LlPB4DDv
8 | 2v8BZNlxDRyKbVC9vAJIfznJiYnV2mCZIVQad982nKPRmrNugGLl/cR/tc4q1F0Q
9 | Do6KRrLOZV2S4f+fZ11CRmMIbPPgcBNIyfOSXLUrcAugbxUBFsRX8qIUGF8V8ehn
10 | iv8pMYa1mwBGrS42srqZjpMlBCQi/XyrubtMdoq2CVZX2GvnxQ85uqUO1qVhZEbI
11 | A5ufEqiGxAW68SK7asa5ir7+wvxDDFbwGPYj8XZ38mvqMjeFpWWEFxIWvx5Rqc89
12 | VOytlHG14LTmh5gT+VmKSCUaL4ImxcmiNzhoeD5L45u+TfUCLV0gr9ES5xq2eGYX
13 | bR3//yAGtKjUTyfFYsDCy00k7ij+uI16zGBTpom5fY6nu0gssf9Vto5pJLFUQ1Uz
14 | cPpUhVPHq7HlKst978tzPUrQAfHA1a7ZbP6sLJhcQEzFRL53pTwHCMuKMMgS4tw6
15 | cuxivaz47OPBKLtxr6ElZtwCtlEn4tKNp5nXyAH3JmByDcHu7EgfUsmnhBI/2Udn
16 | xjO4BWziAeyOekewxJ9cq4njGPaTxQKVEeTsB4aw4T/4mIoihuvsDSP4IyoiSvCo
17 | FvF6ZEpsY2RXutYHAeL0krq0UUugmWciWBC7hVJna0WeO6MYtLv82dkOATwlT0CA
18 | UVJwcwJoqfNVuwkiVNSdSGpirVV/tNBoa7HLCCJ2mNE0oegC3fxm7OJuL5bH3r1t
19 | G5cU91aYl7aIt0x0fydbIYAJ9+t+rGlFnPgE0AaygykDulfqdZigHxXRkKoDs7n3
20 | CcP+8EEC9kclOCVruRgi4V+zkwAXam4ANbLkUwidvjdAUELRnojLM/0D8ghqplId
21 | TssgGg57HgYOMEG/6Q1mOptZXyJFI8A1zn2svm9/f3AkhTqkJP3JoaaXkJeNXsI8
22 | 64DbVHGRFT9RI/00SwAw+bmkqZaUZLzlwEBAE+Lx/cSyWUK/NYsWmm+WFYybX+54
23 | ReK7QEQO7+pPXIOoTcpFGL3Csg4X4bqdqjQU9nx34ZTJ/D9IJ9lW/m+bRthoty2z
24 | pIDb1vIPnsT0abponp7WPlJDe8fccZE3YEDwnu5U8x3vNLKvTI0no/7+o5B7a6z4
25 | /cJFEwRH0n9eJ/riuykQCYon8f4UNRg4RlxPXoG/RXiZ39YndGbWPa2/KZWJmviB
26 | 92jCaB6cy06VYJs6pW/S3C5wEsFVO85pK7ZqWrhGLcVb57y0OvDhrNjQkvIYFXp2
27 | TV1FEN1H2M36iDTFdsJvs0SV8Jf6w+aErm2zEKInSdBVyQEtDyugwaH9Wpd1LF5g
28 | zXxmzfoazmQ7/too4GXW3sYKkAew2UqbICe/OpxKf16sdnQNnu/xpolQlLsbWwv+
29 | visB0D1qQLy2tEAUXk9UYMcGoFUm5un39ZJI5PWmCJ5o
30 | -----END ENCRYPTED PRIVATE KEY-----
31 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo2.client_cert/demo2.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/demo/nginx_client_auth/certs/demo2.client_cert/demo2.p12
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo2.client_cert/demo2.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
34 | VJhAWAW2zZ26Z3//Uwmgo79DYxa53w==
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/demo2.client_cert/rootca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/int.crl.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN X509 CRL-----
2 | MIIDBjCB7wIBATANBgkqhkiG9w0BAQsFADCBljELMAkGA1UEBhMCTkwxFjAUBgNV
3 | BAgMDU5vb3JkIEhvbGxhbmQxEjAQBgNVBAcMCUFtc3RlcmRhbTEPMA0GA1UECgwG
4 | Qm91bkNBMQswCQYDVQQLDAJJVDEfMB0GA1UEAwwWQm91bkNBIEludGVybWVkaWF0
5 | ZSBDQTEcMBoGCSqGSIb3DQEJARYNY2FAYm91bmNhLm9yZxcNMjExMjI4MTIwMDI0
6 | WhcNMjExMjI5MTMxMjI3WjAkMCICEQCQJoYwx3RDBKri9mPaRLAZFw0yMTEyMjgx
7 | MzEyMjdaMA0GCSqGSIb3DQEBCwUAA4ICAQCgU621d5MxCg92ic3h4DX6///36YA3
8 | ytBtggaS507vK8ejzjWb6D7l9X1iPRwuthpWvThzn4x3QNzoIctt8y+isn2UiBcV
9 | GHMcvyeMXwLcAKaeK61fA3aWn+81qs3K8gew0UdB5HeQK3I/8Yvr+FoF+K4wNIrX
10 | eEgaWE898P33psum96/t9CNZymMBTK4tQlM0pQ6JlC2/gtFCQG4MFYqjjqJqsp/q
11 | LW/ZH5yqCxbjEysf42uAYRG+vdFZuRVYwWYdRj47F+LZLlGCkxaCcKuT2hSQ+CJr
12 | U3QzJuO0cpP+GtGljunERNPutNktCGWx3AHoGOVwvpSkTvSpqHOWCZWMje+X04Vm
13 | vnaAiFltG/KYQwEKugp+R+3lv9khN4cTm503AXJfmun52bQ+Oj/2fSAQZK3u/TIn
14 | 6xJInkEDyoap3+poj4OY2xUgNezBzGMUmmtRCd/yiS4YCD4PBp5qMdzVWtYXSJvi
15 | 9opTWJEMMJp+VOBu3M5CFIzUe7J9ZhOuuUEMZ31fOaeceARt+EtO5jiiP/4dqgm+
16 | uCjy9btvk03FZKeZFQImU3rBLxdoZB7ZwWYMkAY0lMz5gzcA69lJuPI4BmhrfZeG
17 | EcXNAD0PfniNIXtTPOgwcQDHwe+KkyUdkM2lzssUEBeIWNDAMT3uSSGz6LTK9Hfr
18 | jtjO1tOMK9Fm6g==
19 | -----END X509 CRL-----
20 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/localhost.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDyiSV8zlryxBHZ
3 | y5CI3TXOeXxvSLI7pmbsqmha5KPwjB/N4PH1Vfq4mdS6WaqhGoFPan9GZ8okH7AV
4 | 08ALlrifAz6XMLk3qZpYeSJzmz+Ydl3P8Ay82yr9B4SNL+Ze/rIv6MyzIH9iZHnd
5 | a6iqUlL6JSovE6SeqPgheguk2N44lSZq5YOIfN4tUX2oW4GOkPufciMfxXVOb7NM
6 | D8/8bFyibNrZK2PGdGNQs+nFQBVyVLd7zr8thdVAoL3Sm4tzoyYKecz4kpAEXfOz
7 | Wxb2gMYjUL7+EpKdlmRnBm207PiaJ5rONF2D682lnURKraFYWmAdcoFLQB1rqwVN
8 | P4OO2XFTAgMBAAECggEBAKni60FbAlXehWp7rshPuyrf6gvBbideTeYlD2frk/Ih
9 | FP4PPSzOhwrbpijKOj0S5dUNEg3tEajwEVWYt4Lmlne7vBIHbRXSVWz3nOxBqPBQ
10 | qTHIQgPfuWL36x9CmCmeWo44kXo/nzr6impQyRpVBA54De5f4gXI8dXxOUrFJhOW
11 | +PVMAEca/cb3aMZLJrA0s0+zN1BuFAHMsf3uGG6dOApnHoE2VqaHwzRa/kERRFjL
12 | omhQ8E/vh9wROzeFIitpvyFD4EdJx68j+3gi4715ZWh7+HTRhhYjbj5SwJA5UIOw
13 | 2arQFOf3NR4hOJAiZ5cmgBqiarOj1lEI3HRRhZrUdyECgYEA+sROAe5+RGa9TFv4
14 | rlZTTJ9MfohBga9uUppWwtOV0kaaN3fU+3JgBUKLqhfpZl76cpMIFYmxkxRpsfZY
15 | mrHNgmExaTU3rfmxa0UIoCNqllnqwBFp9ENaWjJsLxsRbvIStuLxIAJNpBGB32iW
16 | 56Up2UB/CEcWPqIfU+QZoDYOjqkCgYEA95jeNXxadCf2VMz+intgKTFuIhy7oyPe
17 | rmJVbcPKsSyMiP1mYTU0gzHkHDtYGoaCgNjUn3xTRccG4SliU85QwbmHBIIQTpz7
18 | 3Mg57YEGquhoaSpqCGNZcuQaqGf9/0Al8nnQPaxg77JuRRPno1Q92+wji/zSXL84
19 | 7YJGvvOwKZsCgYBRWg/ohoOGE0KEHC4v+Kdrax54yiFePhhvScytxdCL+AWdyw1Y
20 | SYGnEzCWDM3WPSfItbRgsFvgWDX12vJhtR7zli5ecDpRAXkyUKH8uaChiCglCUEz
21 | UgpkyojYO1LLiFLT7AnHlZe0i01zuc2C9sz9wvOzLsSjqxq4r340wHS2iQKBgQDq
22 | 6Cwajqq6/ZcmCX+OH1OygWU+FAip1URWKpFmnJXX1q5W4iOaIoJ53oHPjzYdpHR4
23 | jj/cOHZBA30xbrQNUvcndT/2NPgHvcTvSUA8Z2fOCsXU0RrcbnXVHTl1gYRoAZJ/
24 | JLc/bCZkA+O+wg3I1goCd12aWPm0aPA31pwMWuNN9QKBgC476ygz9uoACtEGSa4Q
25 | uarDu292UpBzO/g1ebtsWCUCWCYIrX3KHEFVjJdVuyYcp3f+TAdG/o77DVDAStPT
26 | MwieYxh47waXTgN6R78tRNTTbEeC7A7915w1Lm6ZDDlr8fzy1QQguBfKgf8OqNzd
27 | AkJZvU/SifJP6Zltv8tv/by7
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/root.crl.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN X509 CRL-----
2 | MIIDBzCB8AIBATANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCTkwxFjAUBgNV
3 | BAgMDU5vb3JkIEhvbGxhbmQxEjAQBgNVBAcMCUFtc3RlcmRhbTEPMA0GA1UECgwG
4 | Qm91bkNBMRcwFQYDVQQLDA5Sb290IEF1dGhvcml0eTEUMBIGA1UEAwwLQm91bkNB
5 | IFJvb3QxHDAaBgkqhkiG9w0BCQEWDWNhQGJvdW5jYS5vcmcXDTIxMTIyNzE3MDg1
6 | M1oXDTIxMTIyOTE1NDUzOVowJDAiAhEA7tEHOpEaTzCK0X7PflUWOBcNMjExMjI4
7 | MTU0NTM5WjANBgkqhkiG9w0BAQsFAAOCAgEAI6Z0D5J/Yae+adtfwwOYG4bYRLv5
8 | dOPjvvrCGmL6xD/9B/EXdEeXcjXrYp+jKwOO7jvJOJwBuuJUvvzILC3Jh/E7bx88
9 | ORauVSIbpqL9OeOdR7doHCX1UudyH7QhLcLsUFr12G7PTGomYC7CHtHg4o0DUmZh
10 | gNRth9yNxsfbfBwAC+PsLQSUULeIz78TwC0O4KO3NnNBgr5iMNbbT+oe+ulx0dJ5
11 | YDFe2C0ilSFue5mvAjSV8UCrAPJdoSElBRluFkadYac02T5vBe/Gm6MQHeA42Fca
12 | 0M7H1X/fnQvc3v8mssHLTr6VaVgY5sAJ02cCbOuKmLLAME9khb3JtVlfeXiEMbRt
13 | d7L/dfMubTSPaud+/zpXIpJfrGi2gI4jg/eOIBihceN3CRNh3qr5i+VhenXD+tsi
14 | Z6Y8EoZvFNBMpCZMqLTl0T0m9CGC/eUSim9Oa+PAHt7brucMzIY9y6jtrt91GifI
15 | wf4vavNTozgwmztfoULhKRkNMIZwWEFU09BvEs05HwQo8SAD++eLQaj1lPJtVQbA
16 | f4AToQo/e9iUnRFk7ki/mQY7mZsAckV2tMxpRC2dbrngC1YlcFDnyxxJYndAh1dL
17 | y/pWRS2cz1yscn7D6RGyT9QKrsGHTe2n7P9AAEnC2jNTe+YpQr82Bq7kNuc82ELz
18 | TjAyCUwArDI3Hm8=
19 | -----END X509 CRL-----
20 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/certs/rootca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | nginx:
4 | image: nginx:1.16.0-alpine
5 | volumes:
6 | - ./nginx.conf:/etc/nginx/nginx.conf:ro
7 | - ./certs/:/etc/nginx/certs/
8 | - ./www/:/var/www/
9 |
10 | ports:
11 | - "8443:443"
12 | - "8800:80"
13 | # Run nginx in debug mode to debug SSL issues:
14 | # command: [nginx-debug, '-g', 'daemon off;']
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/nginx.conf:
--------------------------------------------------------------------------------
1 | events {}
2 |
3 | http{
4 | server {
5 | listen 80;
6 | server_name localhost;
7 | return 301 https://$server_name:8443$request_uri;
8 | }
9 |
10 | server {
11 | listen 443 ssl;
12 | server_name localhost;
13 | ssl_certificate /etc/nginx/certs/localhost-chain.pem;
14 | ssl_certificate_key /etc/nginx/certs/localhost.key;
15 |
16 | access_log /var/log/nginx/access.log;
17 | error_log /var/log/nginx/error.log debug;
18 |
19 | # curl --cacert rootca.pem --cert demo1.pem --key demo1.key --pass demo1Demo1 https://localhost:8443
20 | # curl --cacert rootca.pem --cert demo2.pem --key demo2.key --pass demo2Demo2 https://localhost:8443
21 |
22 | ssl_client_certificate /etc/nginx/certs/BounCA_Int_Root.intermediate-chain.pem;
23 | ssl_verify_depth 2;
24 | # make verification optional, so we can display a (custom) 403 message to those
25 | # who fail authentication. Option can also be 'on', in that case nging will drop a default error.
26 | ssl_verify_client optional;
27 |
28 | # Concatenate all crls of the chain to one file, in this case the root and intermediate crl
29 | ssl_crl /etc/nginx/certs/root_int.crl;
30 |
31 | # Nginx doesn't check the intermediate certificate, add the following rule to check for the correct intermediate chain
32 | # you can fetch the subject by the following command: openssl x509 -in intermediate.pem -noout -subject
33 | # you can expose the value of $ssl_client_i_dn by adding a header in the location scope: add_header X-debug-message "$ssl_client_i_dn" always;
34 |
35 | if ($ssl_client_i_dn != "emailAddress=ca@bounca.org,CN=BounCA Intermediate CA,OU=IT,O=BounCA,L=Amsterdam,ST=Noord Holland,C=NL") {
36 | return 403;
37 | }
38 |
39 | location / {
40 |
41 | if ($ssl_client_verify != SUCCESS) {
42 | return 403;
43 | }
44 | root /var/www;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_client_auth/www/index.html:
--------------------------------------------------------------------------------
1 | Hello World - Your Client Certificate is working!!
2 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_ssl/certs/localhost.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDyiSV8zlryxBHZ
3 | y5CI3TXOeXxvSLI7pmbsqmha5KPwjB/N4PH1Vfq4mdS6WaqhGoFPan9GZ8okH7AV
4 | 08ALlrifAz6XMLk3qZpYeSJzmz+Ydl3P8Ay82yr9B4SNL+Ze/rIv6MyzIH9iZHnd
5 | a6iqUlL6JSovE6SeqPgheguk2N44lSZq5YOIfN4tUX2oW4GOkPufciMfxXVOb7NM
6 | D8/8bFyibNrZK2PGdGNQs+nFQBVyVLd7zr8thdVAoL3Sm4tzoyYKecz4kpAEXfOz
7 | Wxb2gMYjUL7+EpKdlmRnBm207PiaJ5rONF2D682lnURKraFYWmAdcoFLQB1rqwVN
8 | P4OO2XFTAgMBAAECggEBAKni60FbAlXehWp7rshPuyrf6gvBbideTeYlD2frk/Ih
9 | FP4PPSzOhwrbpijKOj0S5dUNEg3tEajwEVWYt4Lmlne7vBIHbRXSVWz3nOxBqPBQ
10 | qTHIQgPfuWL36x9CmCmeWo44kXo/nzr6impQyRpVBA54De5f4gXI8dXxOUrFJhOW
11 | +PVMAEca/cb3aMZLJrA0s0+zN1BuFAHMsf3uGG6dOApnHoE2VqaHwzRa/kERRFjL
12 | omhQ8E/vh9wROzeFIitpvyFD4EdJx68j+3gi4715ZWh7+HTRhhYjbj5SwJA5UIOw
13 | 2arQFOf3NR4hOJAiZ5cmgBqiarOj1lEI3HRRhZrUdyECgYEA+sROAe5+RGa9TFv4
14 | rlZTTJ9MfohBga9uUppWwtOV0kaaN3fU+3JgBUKLqhfpZl76cpMIFYmxkxRpsfZY
15 | mrHNgmExaTU3rfmxa0UIoCNqllnqwBFp9ENaWjJsLxsRbvIStuLxIAJNpBGB32iW
16 | 56Up2UB/CEcWPqIfU+QZoDYOjqkCgYEA95jeNXxadCf2VMz+intgKTFuIhy7oyPe
17 | rmJVbcPKsSyMiP1mYTU0gzHkHDtYGoaCgNjUn3xTRccG4SliU85QwbmHBIIQTpz7
18 | 3Mg57YEGquhoaSpqCGNZcuQaqGf9/0Al8nnQPaxg77JuRRPno1Q92+wji/zSXL84
19 | 7YJGvvOwKZsCgYBRWg/ohoOGE0KEHC4v+Kdrax54yiFePhhvScytxdCL+AWdyw1Y
20 | SYGnEzCWDM3WPSfItbRgsFvgWDX12vJhtR7zli5ecDpRAXkyUKH8uaChiCglCUEz
21 | UgpkyojYO1LLiFLT7AnHlZe0i01zuc2C9sz9wvOzLsSjqxq4r340wHS2iQKBgQDq
22 | 6Cwajqq6/ZcmCX+OH1OygWU+FAip1URWKpFmnJXX1q5W4iOaIoJ53oHPjzYdpHR4
23 | jj/cOHZBA30xbrQNUvcndT/2NPgHvcTvSUA8Z2fOCsXU0RrcbnXVHTl1gYRoAZJ/
24 | JLc/bCZkA+O+wg3I1goCd12aWPm0aPA31pwMWuNN9QKBgC476ygz9uoACtEGSa4Q
25 | uarDu292UpBzO/g1ebtsWCUCWCYIrX3KHEFVjJdVuyYcp3f+TAdG/o77DVDAStPT
26 | MwieYxh47waXTgN6R78tRNTTbEeC7A7915w1Lm6ZDDlr8fzy1QQguBfKgf8OqNzd
27 | AkJZvU/SifJP6Zltv8tv/by7
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_ssl/certs/rootca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | 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
35 | -----END CERTIFICATE-----
36 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_ssl/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | nginx:
4 | image: nginx:1.16.0-alpine
5 | volumes:
6 | - ./nginx.conf:/etc/nginx/nginx.conf:ro
7 | - ./certs/:/etc/nginx/certs/
8 | - ./www/:/var/www/
9 |
10 | ports:
11 | - "8443:443"
12 | - "8800:80"
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_ssl/nginx.conf:
--------------------------------------------------------------------------------
1 | events {}
2 |
3 | http{
4 | server {
5 | listen 80;
6 | server_name localhost;
7 | return 301 https://$server_name:8443$request_uri;
8 | }
9 |
10 | server {
11 | listen 443 ssl;
12 | server_name localhost;
13 | ssl_certificate /etc/nginx/certs/localhost-chain.pem;
14 | ssl_certificate_key /etc/nginx/certs/localhost.key;
15 |
16 | access_log /var/log/nginx/access.log;
17 | error_log /var/log/nginx/error.log info;
18 |
19 | location / {
20 | root /var/www;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/docs/source/demo/nginx_ssl/www/index.html:
--------------------------------------------------------------------------------
1 | Hello World - SSL connection via BounCA generated certificate
2 |
--------------------------------------------------------------------------------
/docs/source/images/BounCA-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/BounCA-logo.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/1-empty-root-dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/1-empty-root-dashboard.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/10-inspect-intermediate-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/10-inspect-intermediate-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/11-inspect-intermediate-certificate-crl-ocsp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/11-inspect-intermediate-certificate-crl-ocsp.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/2-create-root-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/2-create-root-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/20-install-root-pem-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/20-install-root-pem-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/20-listed-root-pem-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/20-listed-root-pem-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/21-inspect-root-pem-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/21-inspect-root-pem-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/22-trust-root-ca-pem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/22-trust-root-ca-pem.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/24-trusted-self-signed-root-ca-pem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/24-trusted-self-signed-root-ca-pem.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/26-root-ca-is-trusted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/26-root-ca-is-trusted.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/27-generate-app-token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/27-generate-app-token.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/3-create-root-certificate-crl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/3-create-root-certificate-crl.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/4-root-certificate-generated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/4-root-certificate-generated.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/5-inspect-root-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/5-inspect-root-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/6-inspect-root-certificate-X.509v3-extensions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/6-inspect-root-certificate-X.509v3-extensions.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/7-enter-root-ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/7-enter-root-ca.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/8-generate-intermediate-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/8-generate-intermediate-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/9-generate-intermediate-certificate-enter-passphrases.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/9-generate-intermediate-certificate-enter-passphrases.png
--------------------------------------------------------------------------------
/docs/source/images/generate-ca-certificates/9-generated-intermediate-ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-ca-certificates/9-generated-intermediate-ca.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/12-enter-int-ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/12-enter-int-ca.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/13-open-client-certificate-create-form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/13-open-client-certificate-create-form.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/14-fill-in-the-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/14-fill-in-the-data.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/15-enter-the-passphrase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/15-enter-the-passphrase.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/16-create-a-second-client-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/16-create-a-second-client-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/17-enter-passphrase-of-second-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/17-enter-passphrase-of-second-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/18-overview-generated-certificates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/18-overview-generated-certificates.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/20-enter-passphrase-of-intermediate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/20-enter-passphrase-of-intermediate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/21-revoked-demo2-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/21-revoked-demo2-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/22-download-intermediate-chain-and-crl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/22-download-intermediate-chain-and-crl.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/31-verify-demo1-2-certificates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/31-verify-demo1-2-certificates.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/32-content-of-intermediate-crl-file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/32-content-of-intermediate-crl-file.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/33-check-revoked-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/33-check-revoked-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/34-no-client-cert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/34-no-client-cert.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/35-valid-client-cert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/35-valid-client-cert.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/36-revoked-client-cert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/36-revoked-client-cert.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/40-adding-client-certificate-to-keychain-of-macOS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/40-adding-client-certificate-to-keychain-of-macOS.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/41-added-client-certificate-to-keychain-of-macOS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/41-added-client-certificate-to-keychain-of-macOS.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/42-inspect-client-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/42-inspect-client-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/43-visit-mTLS-site-safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/43-visit-mTLS-site-safari.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/44-granted-mTLS-safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/44-granted-mTLS-safari.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/45-visit-mTLS-chrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/45-visit-mTLS-chrome.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/46-granted-mTLS-chrome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/46-granted-mTLS-chrome.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/47-certificate-management-firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/47-certificate-management-firefox.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/48-import-pkcs12-in-firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/48-import-pkcs12-in-firefox.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/49-client-certificate-added-in-firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/49-client-certificate-added-in-firefox.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/50-visit-mTLS-firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/50-visit-mTLS-firefox.png
--------------------------------------------------------------------------------
/docs/source/images/generate-client-certificate/51-granted-mTLS-firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-client-certificate/51-granted-mTLS-firefox.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/12-enter-int-ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/12-enter-int-ca.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/14-fill-in-the-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/14-fill-in-the-data.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/15-enter-the-passphrase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/15-enter-the-passphrase.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/16-generated-smime-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/16-generated-smime-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/17-inspect-subject-client-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/17-inspect-subject-client-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/18-inspect-subject-alt-names-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/18-inspect-subject-alt-names-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/19-install-client-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/19-install-client-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/20-create-signed-mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/20-create-signed-mail.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/21-received-signed-mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/21-received-signed-mail.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/22-received-signed-mail-thunderbird-not-trusted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/22-received-signed-mail-thunderbird-not-trusted.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/23-add-root-certificate-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/23-add-root-certificate-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/24-trust-root-certificate-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/24-trust-root-certificate-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/25-received-signed-mail-trusted-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/25-received-signed-mail-trusted-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/26-add-client-certificate-to-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/26-add-client-certificate-to-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/27-select-p12-file-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/27-select-p12-file-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/28-client-certificate-added-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/28-client-certificate-added-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/29-select-client-certificate-to-sign-and-encrypt-mail-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/29-select-client-certificate-to-sign-and-encrypt-mail-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/30-client-certificate-configured-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/30-client-certificate-configured-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/31-send-signed-mail-thunderbird.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/31-send-signed-mail-thunderbird.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/32-send-encrypted-mail-Mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/32-send-encrypted-mail-Mail.png
--------------------------------------------------------------------------------
/docs/source/images/generate-mail-certificate/33-received-encrypted-mail-Firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-mail-certificate/33-received-encrypted-mail-Firefox.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/12-enter-int-ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/12-enter-int-ca.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/13-copy-data-from-intermediate-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/13-copy-data-from-intermediate-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/13-create-ssl-server-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/13-create-ssl-server-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/14-enter-passphrase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/14-enter-passphrase.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/14-enter-subject-alternative-names.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/14-enter-subject-alternative-names.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/15-inspect-server-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/15-inspect-server-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/15-server-certificate-generated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/15-server-certificate-generated.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/16-inspect-server-certificate-crl-ocsp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/16-inspect-server-certificate-crl-ocsp.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/18-ssl-certificate-zip-package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/18-ssl-certificate-zip-package.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/19-check-ssl-certificate-chain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/19-check-ssl-certificate-chain.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/26-root-ca-is-trusted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/26-root-ca-is-trusted.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/28-visit-website-trusted-ssl-connection-https.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/28-visit-website-trusted-ssl-connection-https.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/30-renew-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/30-renew-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/31-renew-certificate-form.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/31-renew-certificate-form.png
--------------------------------------------------------------------------------
/docs/source/images/generate-server-certificate/32-certificate-renewed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/generate-server-certificate/32-certificate-renewed.png
--------------------------------------------------------------------------------
/docs/source/images/hex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/hex.png
--------------------------------------------------------------------------------
/docs/source/images/hexa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/hexa.png
--------------------------------------------------------------------------------
/docs/source/images/ico/android-chrome-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/android-chrome-144x144.png
--------------------------------------------------------------------------------
/docs/source/images/ico/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/android-chrome-192x192.png
--------------------------------------------------------------------------------
/docs/source/images/ico/android-chrome-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/android-chrome-36x36.png
--------------------------------------------------------------------------------
/docs/source/images/ico/android-chrome-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/android-chrome-48x48.png
--------------------------------------------------------------------------------
/docs/source/images/ico/android-chrome-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/android-chrome-72x72.png
--------------------------------------------------------------------------------
/docs/source/images/ico/android-chrome-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/android-chrome-96x96.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/docs/source/images/ico/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/apple-touch-icon.png
--------------------------------------------------------------------------------
/docs/source/images/ico/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | #da532c
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/source/images/ico/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/source/images/ico/favicon-194x194.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/favicon-194x194.png
--------------------------------------------------------------------------------
/docs/source/images/ico/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/source/images/ico/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/favicon-96x96.png
--------------------------------------------------------------------------------
/docs/source/images/ico/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/favicon.ico
--------------------------------------------------------------------------------
/docs/source/images/ico/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BounCA",
3 | "icons": [
4 | {
5 | "src": "\/static\/bounca\/img\/ico\/android-chrome-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": 0.75
9 | },
10 | {
11 | "src": "\/static\/bounca\/img\/ico\/android-chrome-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": 1
15 | },
16 | {
17 | "src": "\/static\/bounca\/img\/ico\/android-chrome-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": 1.5
21 | },
22 | {
23 | "src": "\/static\/bounca\/img\/ico\/android-chrome-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": 2
27 | },
28 | {
29 | "src": "\/static\/bounca\/img\/ico\/android-chrome-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": 3
33 | },
34 | {
35 | "src": "\/static\/bounca\/img\/ico\/android-chrome-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": 4
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/docs/source/images/ico/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/mstile-144x144.png
--------------------------------------------------------------------------------
/docs/source/images/ico/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/mstile-150x150.png
--------------------------------------------------------------------------------
/docs/source/images/ico/mstile-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/mstile-310x150.png
--------------------------------------------------------------------------------
/docs/source/images/ico/mstile-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/mstile-310x310.png
--------------------------------------------------------------------------------
/docs/source/images/ico/mstile-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/ico/mstile-70x70.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/1_chrome_open_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/1_chrome_open_settings.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/1_firefox_open_settings_page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/1_firefox_open_settings_page.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/20-install-root-pem-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/20-install-root-pem-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/20-listed-root-pem-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/20-listed-root-pem-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/21-inspect-root-pem-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/21-inspect-root-pem-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/22-trust-root-ca-pem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/22-trust-root-ca-pem.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/24-trusted-self-signed-root-ca-pem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/24-trusted-self-signed-root-ca-pem.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/26-root-ca-is-trusted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/26-root-ca-is-trusted.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/2_chrome_click_on_advanced_settings_and_go_to_certificates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/2_chrome_click_on_advanced_settings_and_go_to_certificates.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/2_firefox_click_on_advanced_settings_and_go_to_certificates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/2_firefox_click_on_advanced_settings_and_go_to_certificates.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/3_chrome_click_on_authorities_and_press_import_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/3_chrome_click_on_authorities_and_press_import_button.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/3_firefox_import_the_root_certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/3_firefox_import_the_root_certificate.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/4_chrome_select_the_root_certificate_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/4_chrome_select_the_root_certificate_file.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/4_firefox_select_the_root_certificate_file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/4_firefox_select_the_root_certificate_file.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/5_chrome_add_the_certificate_and_select_trust_rules.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/5_chrome_add_the_certificate_and_select_trust_rules.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/5_firefox_select_the_trust_rules.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/5_firefox_select_the_trust_rules.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/6_chrome_certificate_is_added_to_authorities_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/6_chrome_certificate_is_added_to_authorities_list.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/6_firefox_the_root_certificate_has_been_added.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/6_firefox_the_root_certificate_has_been_added.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/7_chrome_inspect_the_certificate_by_clicking_on_view_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/7_chrome_inspect_the_certificate_by_clicking_on_view_button.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/7_firefox_inspect_the_root_certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/7_firefox_inspect_the_root_certificate.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/8_chrome_visit_self-signed_website_and_verify_it_is_trusted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/8_chrome_visit_self-signed_website_and_verify_it_is_trusted.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/8_firefox_visit_self-signed_website_and_verify_it_is_trusted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/8_firefox_visit_self-signed_website_and_verify_it_is_trusted.png
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/ios_certificate_installed.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/ios_certificate_installed.jpg
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/ios_open_certificate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/ios_open_certificate.jpg
--------------------------------------------------------------------------------
/docs/source/images/install_root_certificate/ios_trust_new_certificate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/install_root_certificate/ios_trust_new_certificate.jpg
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/adding_new_intermediate_certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/adding_new_intermediate_certificate.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/client_server_certificate_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/client_server_certificate_overview.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/intermediate_certificate_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/intermediate_certificate_overview.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/revoke_certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/revoke_certificate.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/revoked_certificate_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/revoked_certificate_overview.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/root_ca_dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/root_ca_dashboard.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/root_certificate_info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/root_certificate_info.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/ssl_dashboard_bounca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/ssl_dashboard_bounca.png
--------------------------------------------------------------------------------
/docs/source/images/main/bounca/validated_certificate_chain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/bounca/validated_certificate_chain.png
--------------------------------------------------------------------------------
/docs/source/images/main/create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/create.png
--------------------------------------------------------------------------------
/docs/source/images/main/easy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/easy.png
--------------------------------------------------------------------------------
/docs/source/images/main/integrate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/integrate.png
--------------------------------------------------------------------------------
/docs/source/images/main/manage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/manage.png
--------------------------------------------------------------------------------
/docs/source/images/main/private.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/private.png
--------------------------------------------------------------------------------
/docs/source/images/main/triangulated_grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/triangulated_grid.png
--------------------------------------------------------------------------------
/docs/source/images/main/world.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/main/world.png
--------------------------------------------------------------------------------
/docs/source/images/readme/ssl_dashboard_bounca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/readme/ssl_dashboard_bounca.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/12-enter-int-ca.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/12-enter-int-ca.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/13-create-openvpn-server-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/13-create-openvpn-server-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/14-passphrase-openvpn-server-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/14-passphrase-openvpn-server-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/15-generate-dh-params.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/15-generate-dh-params.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/20-create-openvpn-client-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/20-create-openvpn-client-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/20-passphrase-openvpn-client-certificate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/20-passphrase-openvpn-client-certificate.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/31-OpenVPN-dashboard-OpenWRT.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/31-OpenVPN-dashboard-OpenWRT.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/32-Demo-VPN-uploaded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/32-Demo-VPN-uploaded.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/33-Inspect-config-Demo-VPN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/33-Inspect-config-Demo-VPN.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/34-Save-Apply-and-start-Demo-VPN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/34-Save-Apply-and-start-Demo-VPN.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/35-Add-firewall-rule-accepting-UDP-OpenVPN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/35-Add-firewall-rule-accepting-UDP-OpenVPN.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/36-Allow-tun-interface-in-local-LAN-zone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/36-Allow-tun-interface-in-local-LAN-zone.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/36a-Allow-tun-interface-in-local-LAN-zone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/36a-Allow-tun-interface-in-local-LAN-zone.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/40-import-ovpn-file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/40-import-ovpn-file.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/41-imported-profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/41-imported-profile.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/42-disconnected-profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/42-disconnected-profile.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/43-enter-passphrase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/43-enter-passphrase.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/44-connected-vpn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/44-connected-vpn.png
--------------------------------------------------------------------------------
/docs/source/images/vpn-configuration/45-browse-to-internal-network.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/docs/source/images/vpn-configuration/45-browse-to-internal-network.png
--------------------------------------------------------------------------------
/docs/source/include_files.rst:
--------------------------------------------------------------------------------
1 | :header_title: Include files
2 |
3 | .. image:: images/main/bounca/revoked_certificate_overview.png
4 |
5 | .. image:: images/main/bounca/client_server_certificate_overview.png
6 |
7 | .. image:: images/main/bounca/adding_new_intermediate_certificate.png
8 |
9 | .. image:: images/main/bounca/intermediate_certificate_overview.png
10 |
11 | .. image:: images/main/bounca/validated_certificate_chain.png
12 |
13 | .. image:: images/main/bounca/root_certificate_info.png
14 |
15 | .. image:: images/main/bounca/root_ca_dashboard.png
16 |
17 | .. image:: images/main/integrate.png
18 |
19 | .. image:: images/main/manage.png
20 |
21 | .. image:: images/main/create.png
22 |
23 | .. image:: images/readme/ssl_dashboard_bounca.png
24 |
25 | .. image:: images/BounCA-logo.png
26 |
27 | .. image:: images/hex.png
28 |
29 |
30 | .. image:: images/ico/apple-touch-icon-57x57.png
31 |
32 | .. image:: images/ico/apple-touch-icon-60x60.png
33 |
34 | .. image:: images/ico/apple-touch-icon-72x72.png
35 |
36 | .. image:: images/ico/apple-touch-icon-76x76.png
37 |
38 | .. image:: images/ico/apple-touch-icon-114x114.png
39 |
40 | .. image:: images/ico/apple-touch-icon-120x120.png
41 |
42 | .. image:: images/ico/apple-touch-icon-144x144.png
43 |
44 | .. image:: images/ico/apple-touch-icon-152x152.png
45 |
46 | .. image:: images/ico/apple-touch-icon-180x180.png
47 |
48 | .. image:: images/ico/favicon-32x32.png
49 |
50 | .. image:: images/ico/android-chrome-192x192.png
51 |
52 | .. image:: images/ico/favicon-96x96.png
53 |
54 | .. image:: images/ico/favicon-16x16.png
55 |
56 | .. image:: images/ico/manifest.json
57 |
58 | .. image:: images/ico/safari-pinned-tab.svg
59 |
60 | .. image:: images/ico/favicon.ico
61 |
62 | .. image:: images/ico/mstile-144x144.png
63 |
64 | .. image:: images/ico/browserconfig.xml
65 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | :launchpage:
2 |
3 |
4 | Site structure
5 | ==============
6 |
7 |
8 | .. _install-docs:
9 |
10 | .. toctree::
11 | :maxdepth: 2
12 | :caption: Getting Started
13 |
14 | getting_started
15 |
16 |
17 | .. _tutorial-docs:
18 |
19 | .. toctree::
20 | :maxdepth: 2
21 | :glob:
22 | :caption: Tutorials
23 |
24 | tutorials/create_certificate_authority
25 | tutorials/install_root_certificate
26 | tutorials/create_server_certificate_webserver
27 | tutorials/create_client_certificate_browser
28 | tutorials/create_mail_certificate
29 | tutorials/vpn_configuration
30 |
31 | .. _about-docs:
32 |
33 | .. toctree::
34 | :maxdepth: 2
35 | :glob:
36 | :caption: About
37 |
38 | bounca/features
39 | bounca/contribution
40 | bounca/support
41 |
42 |
43 |
--------------------------------------------------------------------------------
/etc/bounca/services.yaml.example:
--------------------------------------------------------------------------------
1 | psql:
2 | dbname: bounca
3 | username: bounca
4 | # CHANGE: replace this value with your secret
5 | password: changeit
6 | host: postgres
7 | port: 5432
8 |
9 | admin:
10 | enabled: True
11 | superuser_signup: True
12 |
13 | django:
14 | debug: False
15 | # CHANGE: replace this value with your secret
16 | secret_key: ''
17 | hosts:
18 | # CHANGE: add your hosts here
19 | # - my_ca.my_domain.tld
20 | - localhost
21 | - 127.0.0.1
22 |
23 | mail:
24 | host: localhost
25 | # port: 587 optionally, only for tls and ssl
26 | # username:
27 | # password:
28 | # connection: none # allowed values: none, tls, ssl
29 | admin: admin@example.com
30 | from: no-reply@example.com
31 |
32 | certificate-engine:
33 | # allowed values: ed25519, rsa
34 | # Ed25519 is a a modern, fast and safe key algorithm, however not supported by all operating systems, like MacOS.
35 | # Keep the 'rsa' option if unsure. Root and intermediate keys are 4096 bits, client and server certificates
36 | # use 2048 bits keys.
37 | key_algorithm: rsa
38 |
39 | registration:
40 | # allowed values: mandatory, optional, off
41 | email_verification: off
42 |
--------------------------------------------------------------------------------
/etc/nginx/bounca:
--------------------------------------------------------------------------------
1 | # CHANGE enable in case of SSL
2 | #server {
3 | # listen 80;
4 | # listen [::]:80;
5 | # server_name bounca; # Replace with your domain
6 | # return 301 https://$http_host$request_uri;
7 | # access_log /var/log/nginx/bounca-access.log;
8 | # error_log /var/log/nginx/bounca-error.log;
9 | #}
10 |
11 | server {
12 |
13 | access_log /var/log/nginx/bounca-access.log;
14 | error_log /var/log/nginx/bounca-error.log;
15 |
16 | # configuration for local hosting non-ssl
17 | listen 80;
18 | listen [::]:80;
19 |
20 | # CHANGE in case you want to configure SSL and disable the listen lines above
21 | # ssl enabled
22 | # listen 443 ssl;
23 | # listen [::]:443 ssl;
24 | # ssl_certificate /etc/nginx/ssl/fullchain.pem;
25 | # ssl_certificate_key /etc/nginx/ssl/privkey.pem;
26 |
27 | server_name bounca; # CHANGE Replace with your domain
28 |
29 | location /static {
30 | root /srv/www/bounca/media;
31 | include mime.types;
32 | }
33 | location /api {
34 | include uwsgi_params;
35 | uwsgi_read_timeout 9600;
36 | uwsgi_send_timeout 9600;
37 | uwsgi_pass unix://run/uwsgi/app/bounca/socket;
38 | }
39 | location /admin {
40 | include uwsgi_params;
41 | uwsgi_read_timeout 9600;
42 | uwsgi_send_timeout 9600;
43 | uwsgi_pass unix://run/uwsgi/app/bounca/socket;
44 | }
45 | location / {
46 | root /srv/www/bounca/front/dist;
47 | include mime.types;
48 | try_files $uri $uri/ /index.html;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/etc/uwsgi/bounca.ini:
--------------------------------------------------------------------------------
1 | [uwsgi]
2 | thread=4
3 | master=1
4 | processes=8
5 | vacuum=true
6 | uid = www-data
7 | gid = www-data
8 | chmod-socket = 700
9 | chown-socket = www-data
10 | socket = /run/uwsgi/app/bounca/socket
11 | logto = /var/log/uwsgi/bounca.log
12 | chdir = /srv/www/bounca
13 | home = /srv/www/bounca/env
14 | module = bounca.wsgi:application
15 | plugins = python3
16 |
17 | env = DJANGO_SETTINGS_MODULE=bounca.settings
18 |
--------------------------------------------------------------------------------
/front/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/front/.env:
--------------------------------------------------------------------------------
1 | VUE_APP_ROOT_API = 'http://localhost:8000'
2 |
--------------------------------------------------------------------------------
/front/.env.production:
--------------------------------------------------------------------------------
1 | VUE_APP_ROOT_API = ''
2 |
--------------------------------------------------------------------------------
/front/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /test/unit/coverage/
5 | /src/components/forms/*
6 |
--------------------------------------------------------------------------------
/front/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint',
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
12 | // consider switching to `plugin:vue/strongly-recommended` or
13 | // `plugin:vue/recommended` for stricter rules.
14 | extends: ['plugin:vue/essential', 'airbnb-base'],
15 | // required to lint *.vue files
16 | plugins: [
17 | 'vue',
18 | ],
19 |
20 | // add your custom rules here
21 | rules: {
22 | // In an arrow function, this does not refer to the owner of the function.
23 | // https://michaelnthiessen.com/this-is-undefined/
24 | 'object-shorthand': 'off',
25 | // don't require .vue extension when importing
26 | 'import/extensions': ['error', 'always', {
27 | js: 'never',
28 | vue: 'never',
29 | }],
30 | // disallow reassignment of function parameters
31 | // disallow parameter object manipulation except for specific exclusions
32 | 'no-param-reassign': ['error', {
33 | props: true,
34 | ignorePropertyModificationsFor: [
35 | 'state', // for vuex state
36 | 'acc', // for reduce accumulators
37 | 'e', // for e.returnvalue
38 | ],
39 | }],
40 | // allow optionalDependencies
41 | // 'import/no-extraneous-dependencies': ['error', {
42 | // optionalDependencies: ['test/unit/index.js']
43 | // }],
44 | // allow debugger during development
45 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
46 | },
47 | };
48 |
--------------------------------------------------------------------------------
/front/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | plugins: {
5 | 'postcss-import': {},
6 | 'postcss-url': {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | autoprefixer: {},
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/front/Makefile:
--------------------------------------------------------------------------------
1 | runserver:
2 | npm run serve
3 |
4 | build:
5 | npm run build
6 |
7 | production:
8 | npm run build --production
9 |
--------------------------------------------------------------------------------
/front/README.md:
--------------------------------------------------------------------------------
1 | # Bounca webapp frontend
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
--------------------------------------------------------------------------------
/front/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset',
4 | ],
5 | };
6 |
--------------------------------------------------------------------------------
/front/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front",
3 | "version": "0.0.0-dev",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@mdi/font": "^6.5.95",
12 | "@vue/cli-service-global": "^4.5.15",
13 | "axios": "^0.25.0",
14 | "babel-preset-stage-2": "^6.24.1",
15 | "bootstrap": "^4.6.1",
16 | "bootstrap-vue": "^2.21.2",
17 | "core-js": "^3.19.1",
18 | "jquery": "^3.6.0",
19 | "lodash": "^4.17.21",
20 | "material-design-icons-iconfont": "^6.1.1",
21 | "typeface-roboto": "^1.1.13",
22 | "vee-validate": "^3.4.14",
23 | "vue": "^2.6.14",
24 | "vue-cookie": "^1.1.4",
25 | "vue-meta": "^2.4.0",
26 | "vue-router": "^3.5.3",
27 | "vuetify": "^2.6.3",
28 | "vuex": "^3.6.2"
29 | },
30 | "devDependencies": {
31 | "@vue/cli-plugin-babel": "^5.0.0-rc.3",
32 | "@vue/cli-plugin-eslint": "~v5.0.0-alpha.7",
33 | "@vue/cli-service": "^4.5.15",
34 | "babel-core": "^6.22.1",
35 | "babel-eslint": "^8.2.1",
36 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
37 | "babel-loader": "^8.2.3",
38 | "babel-plugin-istanbul": "^6.1.1",
39 | "babel-plugin-syntax-jsx": "^6.18.0",
40 | "babel-plugin-transform-runtime": "^6.22.0",
41 | "babel-plugin-transform-vue-jsx": "^3.5.0",
42 | "babel-polyfill": "^6.26.0",
43 | "babel-preset-env": "^1.3.2",
44 | "babel-register": "^6.22.0",
45 | "eslint": "7.32.0",
46 | "eslint-config-airbnb-base": "15.0.0",
47 | "eslint-friendly-formatter": "3.0.0",
48 | "eslint-import-resolver-webpack": "0.8.3",
49 | "eslint-loader": "4.0.2",
50 | "eslint-plugin-import": "2.25.3",
51 | "eslint-plugin-vue": "8.4.1",
52 | "extract-text-webpack-plugin": "^4.0.0-beta.0",
53 | "postcss": "^8.4.6",
54 | "postcss-import": "12.0.1",
55 | "postcss-loader": "^4.1.0",
56 | "postcss-url": "^9.0.0",
57 | "sass": "~1.32.13",
58 | "sass-loader": "~10.2.0",
59 | "vue-cli-plugin-vuetify": "^2.4.5",
60 | "vue-template-compiler": "^2.6.14",
61 | "vuetify-loader": "^1.7.3",
62 | "webpack": "^4.45.0"
63 | },
64 | "browserslist": [
65 | "> 1%",
66 | "last 2 versions",
67 | "not dead"
68 | ]
69 | }
70 |
--------------------------------------------------------------------------------
/front/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/favicon.ico
--------------------------------------------------------------------------------
/front/public/ico/android-chrome-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/android-chrome-144x144.png
--------------------------------------------------------------------------------
/front/public/ico/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/android-chrome-192x192.png
--------------------------------------------------------------------------------
/front/public/ico/android-chrome-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/android-chrome-36x36.png
--------------------------------------------------------------------------------
/front/public/ico/android-chrome-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/android-chrome-48x48.png
--------------------------------------------------------------------------------
/front/public/ico/android-chrome-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/android-chrome-72x72.png
--------------------------------------------------------------------------------
/front/public/ico/android-chrome-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/android-chrome-96x96.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/front/public/ico/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/apple-touch-icon.png
--------------------------------------------------------------------------------
/front/public/ico/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | #da532c
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/front/public/ico/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/favicon-16x16.png
--------------------------------------------------------------------------------
/front/public/ico/favicon-194x194.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/favicon-194x194.png
--------------------------------------------------------------------------------
/front/public/ico/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/favicon-32x32.png
--------------------------------------------------------------------------------
/front/public/ico/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/favicon-96x96.png
--------------------------------------------------------------------------------
/front/public/ico/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BounCA",
3 | "icons": [
4 | {
5 | "src": "\/ico\/android-chrome-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": 0.75
9 | },
10 | {
11 | "src": "\/ico\/android-chrome-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": 1
15 | },
16 | {
17 | "src": "\/ico\/android-chrome-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": 1.5
21 | },
22 | {
23 | "src": "\/ico\/android-chrome-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": 2
27 | },
28 | {
29 | "src": "\/ico\/android-chrome-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": 3
33 | },
34 | {
35 | "src": "\/ico\/android-chrome-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": 4
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/front/public/ico/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/mstile-144x144.png
--------------------------------------------------------------------------------
/front/public/ico/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/mstile-150x150.png
--------------------------------------------------------------------------------
/front/public/ico/mstile-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/mstile-310x150.png
--------------------------------------------------------------------------------
/front/public/ico/mstile-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/mstile-310x310.png
--------------------------------------------------------------------------------
/front/public/ico/mstile-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/public/ico/mstile-70x70.png
--------------------------------------------------------------------------------
/front/src/App.vue:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/front/src/api/apptokens.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import store from '../store';
3 |
4 | export default {
5 | getAll(params) {
6 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/tokens`;
7 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
8 | return axios.get(url, { params, headers: headers }).then((response) => response.data);
9 | },
10 | get(id) {
11 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/tokens/${id}`;
12 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
13 | return axios.get(url, { headers: headers }).then((response) => response.data);
14 | },
15 | delete(id, data) {
16 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/tokens/${id}`;
17 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
18 | return axios.delete(url, { data: data, headers: headers }).then((response) => response.data);
19 | },
20 | create(data) {
21 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/tokens/`;
22 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
23 | return axios.post(url, data, { headers: headers });
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/front/src/api/auth.js:
--------------------------------------------------------------------------------
1 | import session from './session';
2 |
3 | export default {
4 | login(data) {
5 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/login/`, data);
6 | },
7 | logout() {
8 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/logout/`, {});
9 | },
10 | createAccount(data) {
11 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/registration/`, data);
12 | },
13 | sendAccountPasswordResetEmail(data) {
14 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/password/reset/`, data);
15 | },
16 | resetAccountPassword(data) {
17 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/password/reset/confirm/`, data);
18 | },
19 | verifyAccountEmail(data) {
20 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/registration/verify-email/`, data);
21 | },
22 | resendEmail(data) {
23 | return session.post(`${process.env.VUE_APP_ROOT_API}/api/v1/auth/registration/resend-email/`, data);
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/front/src/api/profile.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import store from '../store';
3 |
4 | export default {
5 | changeAccountPassword(data) {
6 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/password/change/`;
7 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
8 | return axios.post(url, data, { headers: headers });
9 | },
10 | getAccountDetails() {
11 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/user/`;
12 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
13 | return axios.get(url, { headers: headers });
14 | },
15 | updateAccountDetails(data) {
16 | const url = `${process.env.VUE_APP_ROOT_API}/api/v1/auth/user/`;
17 | const headers = { Authorization: `Token ${store.getters['auth/accessToken']}` };
18 | return axios.patch(url, data, { headers: headers });
19 | },
20 |
21 | };
22 |
--------------------------------------------------------------------------------
/front/src/api/session.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const CSRF_COOKIE_NAME = 'csrftoken';
4 | const CSRF_HEADER_NAME = 'X-CSRFToken';
5 |
6 | const session = axios.create({
7 | xsrfCookieName: CSRF_COOKIE_NAME,
8 | xsrfHeaderName: CSRF_HEADER_NAME,
9 | });
10 |
11 | export default session;
12 |
--------------------------------------------------------------------------------
/front/src/assets/img/BounCA-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/front/src/assets/img/BounCA-logo.png
--------------------------------------------------------------------------------
/front/src/components/core/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
12 |
13 | More info and get connected:
14 |
15 |
24 | {{ link.name }}
25 |
26 |
27 |
28 |
29 | © 2016 - {{ (new Date()).getFullYear() }} —
30 |
35 | BounCA.org, made by
36 | Repleo.nl, Amsterdam, The Netherlands
40 |
41 |
42 |
43 |
44 |
45 |
60 |
61 |
66 |
--------------------------------------------------------------------------------
/front/src/components/core/Toolbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
12 |
13 |
14 |
15 |
16 |
17 | BounCA - Key Management
18 |
19 |
20 | V{{ appVersion }}
21 |
22 |
23 |
24 |
25 |
26 | mdi-account
27 | mdi-power
28 |
29 |
30 | sign up
31 | login
32 |
33 |
34 |
35 |
36 |
65 |
--------------------------------------------------------------------------------
/front/src/components/error/NotFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Page Not Found
4 | Home.
5 |
6 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/front/src/components/forms/EmailVerify.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 | {{detail}}
12 |
13 |
14 |
15 |
23 | {{error}}
24 |
25 |
26 |
27 |
28 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
70 |
--------------------------------------------------------------------------------
/front/src/components/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import upperFirst from 'lodash/upperFirst';
3 | import camelCase from 'lodash/camelCase';
4 |
5 | const requireComponent = require.context('@/components', true, /\.vue$/);
6 |
7 | requireComponent.keys().forEach((fileName) => {
8 | const componentConfig = requireComponent(fileName);
9 | const componentName = upperFirst(
10 | camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, '')),
11 | );
12 |
13 | Vue.component(componentName, componentConfig.default || componentConfig);
14 | });
15 |
--------------------------------------------------------------------------------
/front/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Axios from 'axios';
3 | import {
4 | ValidationObserver,
5 | ValidationProvider,
6 | localize,
7 | extend,
8 | setInteractionMode,
9 | } from 'vee-validate';
10 | import en from 'vee-validate/dist/locale/en.json';
11 | import * as rules from 'vee-validate/dist/rules';
12 |
13 | import App from './App.vue';
14 | import router from './router';
15 | import store from './store';
16 |
17 | // Components
18 | import './components/index';
19 |
20 | import vuetify from './plugins/vuetify';
21 |
22 | /* vee-validate config */
23 | setInteractionMode('eager');
24 | Vue.component('extendValidation', extend);
25 | Vue.component('ValidationObserver', ValidationObserver);
26 | Vue.component('ValidationProvider', ValidationProvider);
27 |
28 | // install rules and localization
29 | Object.keys(rules).forEach((rule) => {
30 | extend(rule, rules[rule]);
31 | });
32 | extend('url', {
33 | validate(value) {
34 | const pattern = new RegExp('^(https?:\\/\\/)?' // protocol
35 | + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' // domain name
36 | + '((\\d{1,3}\\.){3}\\d{1,3}))' // OR ip (v4) address
37 | + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' // port and path
38 | + '(\\?[;&a-z\\d%_.~+=-]*)?' // query string
39 | + '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
40 | return pattern.test(value);
41 | },
42 | message: 'Please enter a valid URL',
43 | });
44 | localize('en', en);
45 | /* vee-validate config */
46 |
47 | Vue.config.productionTip = process.env.NODE_ENV === 'production';
48 |
49 | Vue.prototype.$http = Axios;
50 | const key = localStorage.getItem('user-key');
51 | if (key) {
52 | Vue.prototype.$http.defaults.headers.common.Authorization = key;
53 | }
54 |
55 | new Vue({
56 | router,
57 | store,
58 | vuetify,
59 | render: (h) => h(App),
60 | }).$mount('#app');
61 |
--------------------------------------------------------------------------------
/front/src/plugins/vuetify.js:
--------------------------------------------------------------------------------
1 | import 'material-design-icons-iconfont/dist/material-design-icons.css';
2 | import '@mdi/font/css/materialdesignicons.css';
3 | import Vue from 'vue';
4 | import Vuetify from 'vuetify/lib/framework';
5 | import colors from 'vuetify/es5/util/colors';
6 |
7 | Vue.use(Vuetify);
8 |
9 | export default new Vuetify({
10 | icons: {
11 | iconFont: 'md',
12 | },
13 | theme: {
14 | themes: {
15 | light: {
16 | primary: colors.indigo.base,
17 | secondary: colors.teal.base,
18 | accent: colors.red.base,
19 | error: colors.red.base,
20 | warning: colors.deepOrange.base,
21 | info: colors.blueGrey.base,
22 | success: colors.lightGreen.base,
23 | },
24 | },
25 | },
26 | });
27 |
--------------------------------------------------------------------------------
/front/src/router/dashboard.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | path: '/dashboard',
4 | redirect: '/dashboard/overview',
5 | component: () => import('../views/Dashboard.vue'),
6 | children: [
7 | {
8 | path: 'overview',
9 | name: 'Overview',
10 | meta: {
11 | requiresAuth: true,
12 | displayName: 'Overview',
13 | },
14 | component: () => import('../components/dashboard/Overview.vue'),
15 | },
16 | {
17 | path: 'root',
18 | name: 'Root',
19 | meta: {
20 | requiresAuth: true,
21 | displayName: 'Root',
22 | },
23 | component: () => import('../components/dashboard/Root.vue'),
24 | },
25 | {
26 | path: 'intermediate/:id',
27 | name: 'Intermediate',
28 | meta: {
29 | requiresAuth: true,
30 | displayName: 'Intermediate',
31 | },
32 | component: () => import('../components/dashboard/Intermediate.vue'),
33 | },
34 | {
35 | path: 'certificate/:id',
36 | name: 'Certificate',
37 | meta: {
38 | requiresAuth: true,
39 | displayName: 'Certificate',
40 | },
41 | component: () => import('../components/dashboard/Certificate.vue'),
42 | },
43 | {
44 | path: 'user/profile',
45 | name: 'user_profile',
46 | meta: {
47 | requiresAuth: true,
48 | displayName: 'Profile',
49 | },
50 | component: () => import('../components/dashboard/user/UserProfile.vue'),
51 | },
52 | ],
53 | },
54 | ];
55 |
--------------------------------------------------------------------------------
/front/src/router/home.js:
--------------------------------------------------------------------------------
1 | import store from '../store';
2 |
3 | export default [
4 | {
5 | path: '*',
6 | meta: {
7 | name: '',
8 | requiresAuth: true,
9 | },
10 | redirect: {
11 | path: '/dashboard',
12 | },
13 | },
14 | {
15 | path: '/',
16 | meta: {
17 | name: '',
18 | requiresAuth: false,
19 | },
20 | component: () => import('../views/Public.vue'),
21 | // redirect if already signed in
22 | beforeEnter: (to, from, next) => {
23 | if (store.getters['auth/isLoggedIn']) {
24 | next('/dashboard');
25 | } else {
26 | next();
27 | }
28 | },
29 | children: [
30 | {
31 | path: '',
32 | redirect: '/auth/login',
33 | },
34 | ],
35 | },
36 | ];
37 |
--------------------------------------------------------------------------------
/front/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 | import Meta from 'vue-meta';
4 | import axios from 'axios';
5 |
6 | import store from '../store';
7 |
8 | // Routes
9 | import home from './home';
10 | import auth from './auth';
11 | import dashboard from './dashboard';
12 |
13 | Vue.use(Router);
14 |
15 | // Create a new router
16 | const router = new Router({
17 | base: '',
18 | mode: 'history',
19 | routes: home.concat(auth, dashboard),
20 |
21 | scrollBehavior(to, from, savedPosition) {
22 | if (savedPosition) {
23 | return savedPosition;
24 | }
25 | if (to.hash) {
26 | return { selector: to.hash };
27 | }
28 | return { x: 0, y: 0 };
29 | },
30 | });
31 |
32 | router.beforeEach((to, from, next) => {
33 | if (to.matched.some((record) => record.meta.requiresAuth)) {
34 | if (store.getters['auth/isLoggedIn']) {
35 | next();
36 | return;
37 | }
38 | next('/');
39 | } else {
40 | next();
41 | }
42 | });
43 |
44 | Vue.use(Meta);
45 |
46 | export default router;
47 |
48 | axios.interceptors.response.use(
49 | (response) => response,
50 | (error) => {
51 | if (error.response.status === 403 || error.response.status === 401) {
52 | store.dispatch('auth/logout').then(() => router.push('/'));
53 | }
54 | return Promise.reject(error);
55 | },
56 | );
57 |
--------------------------------------------------------------------------------
/front/src/store/auth.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 | import auth from '../api/auth';
3 |
4 | const initialState = {
5 | key: localStorage.getItem('key') || '',
6 | };
7 |
8 | const mutations = {
9 | auth_request(state) {
10 | state.status = 'loading';
11 | },
12 | auth_success(state, key) {
13 | state.status = 'success';
14 | state.key = key;
15 | },
16 | auth_error(state) {
17 | state.status = 'error';
18 | },
19 | logout(state) {
20 | state.status = '';
21 | state.key = '';
22 | },
23 | };
24 |
25 | const actions = {
26 | login({ commit }, credentials) {
27 | return new Promise((resolve, reject) => {
28 | commit('auth_request');
29 | auth.login(credentials).then((resp) => {
30 | const { key } = resp.data;
31 | localStorage.setItem('key', key);
32 | axios.defaults.headers.common.Authorization = key;
33 | commit('auth_success', key);
34 | resolve(resp);
35 | }).catch((err) => {
36 | commit('auth_error');
37 | localStorage.removeItem('key');
38 | reject(err);
39 | });
40 | });
41 | },
42 | register({ commit }, subscription) {
43 | return new Promise((resolve, reject) => {
44 | commit('auth_request');
45 | auth.createAccount(subscription).then((resp) => {
46 | const { key } = resp.data;
47 | localStorage.setItem('key', key);
48 | axios.defaults.headers.common.Authorization = key;
49 | commit('auth_success', key);
50 | resolve(resp);
51 | }).catch((err) => {
52 | commit('auth_error');
53 | localStorage.removeItem('key');
54 | reject(err);
55 | });
56 | });
57 | },
58 | logout({ commit }) {
59 | return new Promise((resolve, reject) => {
60 | auth.logout().then((resp) => {
61 | commit('logout');
62 | localStorage.removeItem('key');
63 | delete axios.defaults.headers.common.Authorization;
64 | resolve(resp);
65 | }).catch((err) => {
66 | reject(err);
67 | });
68 | });
69 | },
70 | };
71 |
72 | const getters = {
73 | isLoggedIn: (state) => !!state.key,
74 | accessToken: (state) => state.key,
75 | };
76 |
77 | export default {
78 | namespaced: true,
79 | state: initialState,
80 | getters,
81 | actions,
82 | mutations,
83 | };
84 |
--------------------------------------------------------------------------------
/front/src/store/dashboard.js:
--------------------------------------------------------------------------------
1 | const initialState = {
2 | navigation: {
3 | root: {
4 | id: '',
5 | name: '',
6 | active: false,
7 | },
8 | intermediate: {
9 | id: '',
10 | name: '',
11 | active: false,
12 | },
13 | },
14 | };
15 |
16 | const getters = { };
17 |
18 | const actions = { };
19 |
20 | const mutations = {
21 | setRoot(state, certInfo) {
22 | state.navigation.root = certInfo;
23 | },
24 | setIntermediate(state, certInfo) {
25 | state.navigation.intermediate = certInfo;
26 | },
27 | };
28 |
29 | export default {
30 | namespaced: true,
31 | state: initialState,
32 | getters,
33 | actions,
34 | mutations,
35 | };
36 |
--------------------------------------------------------------------------------
/front/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 | import createLogger from 'vuex/dist/logger';
4 |
5 | import auth from './auth';
6 | import dashboard from './dashboard';
7 | import version from './version';
8 |
9 | const debug = process.env.NODE_ENV !== 'production';
10 |
11 | Vue.use(Vuex);
12 |
13 | export default new Vuex.Store({
14 | modules: {
15 | auth: auth,
16 | dashboard: dashboard,
17 | version: version,
18 | },
19 | strict: debug,
20 | plugins: debug ? [createLogger()] : [],
21 | });
22 |
--------------------------------------------------------------------------------
/front/src/store/version.js:
--------------------------------------------------------------------------------
1 | const packageJson = JSON.parse(JSON.stringify(require('../../package.json')));
2 |
3 | const initialState = {
4 | packageVersion: packageJson.version,
5 | };
6 |
7 | const getters = {
8 | appVersion: (state) => state.packageVersion,
9 | };
10 |
11 | const actions = { };
12 |
13 | const mutations = { };
14 |
15 | export default {
16 | namespaced: true,
17 | state: initialState,
18 | getters,
19 | actions,
20 | mutations,
21 | };
22 |
--------------------------------------------------------------------------------
/front/src/views/Auth.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/front/src/views/Dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
24 |
25 |
27 |
--------------------------------------------------------------------------------
/front/src/views/Public.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
--------------------------------------------------------------------------------
/front/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transpileDependencies: [
3 | 'vuetify',
4 | ],
5 | pages: {
6 | index: {
7 | // entry for the page
8 | entry: 'src/main.js',
9 | title: 'BounCA PKI',
10 | },
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/graphics/logo/BounCA-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/graphics/logo/BounCA-icon.png
--------------------------------------------------------------------------------
/graphics/logo/BounCA.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/graphics/logo/BounCA.pdf
--------------------------------------------------------------------------------
/graphics/logo/BounCA.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/graphics/logo/BounCA.sketch
--------------------------------------------------------------------------------
/logs/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 |
--------------------------------------------------------------------------------
/make-docs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -e
2 |
3 | WORKDIR=`dirname "$0"`
4 | PYTHON=`which python3`
5 |
6 | virtualenv -p "$PYTHON" env
7 | . env/bin/activate
8 | cd "$WORKDIR"
9 |
10 | pip install -r requirements.docs.txt
11 |
12 | cd docs
13 | make html
14 | cd ..
15 | rm -rf ./bounca/static/docs/* || true
16 | cp -r ./docs/build/html/ ./bounca/static/docs/
17 |
--------------------------------------------------------------------------------
/make-package.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -ex
2 |
3 |
4 | BASEDIR=$(dirname "$0")
5 | WORKDIR="$BASEDIR/out/bounca"
6 | VERSION=$(awk '{ sub(/.*\//, ""); print }' <<< $(git rev-parse --abbrev-ref HEAD))
7 |
8 |
9 | if [ "$VERSION" == "master" ]; then
10 | VERSION="0.0.0-$VERSION"
11 | fi
12 |
13 | cd $BASEDIR
14 | ./run-checks.sh
15 | ./run-tests.sh
16 |
17 |
18 | echo "Archive will be created ./out"
19 | rm -rf $WORKDIR | true
20 | mkdir -p $WORKDIR
21 | git archive master | tar -x -C $WORKDIR
22 |
23 | cd $WORKDIR
24 | rm -rf ./vuetifyforms
25 | cd front
26 |
27 | sed -i '' -e s/\"version\":\ \"0.0.0-dev\"/\"version\":\ \"$VERSION\"/g package.json
28 | npm install
29 | npm run build --production
30 | rm -rf node_modules public src
31 | rm .babelrc .env .env.production .eslintignore .eslintrc.js .postcssrc.js
32 | rm Makefile README.md babel.config.js package-lock.json package.json vue.config.js
33 |
34 | cd "../.."
35 | tar -czvf "bounca-$VERSION.tar.gz" --owner=0 --group=0 bounca/
36 | rm -rf $WORKDIR | true
37 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 |
6 | def main():
7 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bounca.settings")
8 | try:
9 | from django.core.management import execute_from_command_line
10 | except ImportError as exc:
11 | raise ImportError(
12 | "Couldn't import Django. Are you sure it's installed and "
13 | "available on your PYTHONPATH environment variable? Did you "
14 | "forget to activate a virtual environment?"
15 | ) from exc
16 | execute_from_command_line(sys.argv)
17 |
18 |
19 | if __name__ == "__main__":
20 | main()
21 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length = 120
3 | target-version = ['py37', 'py38']
4 | exclude = '''
5 | (
6 | /(
7 | | env
8 | | venv
9 | | out
10 | | .+/migrations
11 | )/
12 | )
13 | '''
14 |
15 |
16 |
17 | [tool.isort]
18 | profile = "black"
19 | multi_line_output = 3
20 | line_length = 120
21 |
22 |
23 | [tool.mypy]
24 | python_version = "3.7"
25 | exclude = "(env|venv|out|migrations|tests|docs)"
26 |
27 | disallow_untyped_calls = false
28 | disallow_untyped_defs = false
29 | disallow_incomplete_defs = false
30 | disallow_untyped_decorators = false
31 |
32 | warn_redundant_casts = true
33 | warn_unused_ignores = true
34 | warn_no_return = true
35 | warn_return_any = true
36 | warn_unreachable = true
37 |
38 | strict_equality = true
39 |
40 | show_error_codes = true
41 | pretty = true
42 |
43 | warn_unused_configs = true
44 | ignore_missing_imports = true
45 |
--------------------------------------------------------------------------------
/requirements.docs.txt:
--------------------------------------------------------------------------------
1 | # Docs
2 | sphinx==5.3.0
3 | sphinx_rtd_theme==1.2.0
4 | sphinx_bootstrap_theme==0.8.1
5 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # Framework
2 | Django==4.2.9
3 | psycopg2-binary==2.9.9
4 | pytz==2023.3.post1
5 | requests==2.31.0
6 | djangorestframework==3.14.0
7 | django-grappelli==3.0.8
8 | django-countries==7.5.1
9 | django-rest-swagger==2.2.0
10 | django-filter==23.5
11 | django-allauth==0.60.1
12 | dj-rest-auth==5.0.2
13 | django-ical==1.9.2
14 | django-cors-headers==4.3.1
15 | django-property-filter==1.2.0
16 |
17 |
18 | # Date
19 | arrow==1.3.0
20 |
21 | # SSL
22 | cryptography==41.0.7
23 | bcrypt==4.1.2
24 |
25 | # Parsers
26 | yamlreader==3.0.4
27 |
28 | # Testing
29 | coverage==7.4.0
30 | factory-boy==3.3.0
31 | Faker==22.2.0
32 | mock==5.1.0
33 | requests-mock==1.11.0
34 |
35 | # Code Quality
36 | flake8==7.0.0
37 | isort==5.13.2
38 | autopep8==2.0.4
39 | mypy==1.8.0
40 | types-pytz==2023.3.1.1
41 | pur==7.3.1
42 | black==23.12.1
43 | typing_extensions==4.9.0
44 |
45 | # Development
46 | beautifulsoup4==4.12.2
47 | django-crispy-forms==2.1
48 | codacy-coverage==1.3.11
49 |
--------------------------------------------------------------------------------
/run-checks-node.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -xe
2 |
3 | BASEDIR=`dirname "$0"`
4 | cd $BASEDIR
5 |
6 | BLUE='\033[1;34m'
7 | BRIGHT_RED='\033[1;31m'
8 | DARK_GRAY='\033[0;37m'
9 | RESET='\033[m'
10 | INFO="${BLUE}[INFO]${RESET}"
11 |
12 | function task() {
13 | if [ "$3" != "" ]; then
14 | printf "$2\n"
15 |
16 | $1 $3 &
17 | pid=$!
18 | wait $pid
19 |
20 | if [ $? == 0 ]; then
21 | echo -ne "\033[0K\r"
22 | else
23 | printf "${BRIGHT_RED}Please fix the above errors ${RESET}\n"
24 | exit 1
25 | fi
26 | fi
27 | }
28 |
29 | PY_MESSAGE="${INFO} Linting javascript files ${DARK_GRAY}[*.js]${RESET}"
30 | cd front
31 | npm install --legacy-peer-deps
32 | task "npm run lint" "$PY_MESSAGE" .
33 |
--------------------------------------------------------------------------------
/run-checks-python.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -x
2 |
3 | PYTHON_FOLDERS='api bounca certificate_engine vuetifyforms x509_pki superuser_signup'
4 | BASEDIR=`dirname "$0"`
5 | cd $BASEDIR
6 |
7 | BLUE='\033[1;34m'
8 | BRIGHT_RED='\033[1;31m'
9 | DARK_GRAY='\033[0;37m'
10 | RESET='\033[m'
11 | INFO="${BLUE}[INFO]${RESET}"
12 |
13 | function task() {
14 | if [ "$3" != "" ]; then
15 | printf "$2\n"
16 |
17 | $1 $3 &
18 | pid=$!
19 | wait $pid
20 |
21 | if [ $? == 0 ]; then
22 | echo -ne "\033[0K\r"
23 | else
24 | printf "${BRIGHT_RED}Please fix the above errors ${RESET}\n"
25 | exit 1
26 | fi
27 | fi
28 | }
29 |
30 | py_files=$(find $PYTHON_FOLDERS -path '**/migrations' -prune -o -name '*.py' -print)
31 | PY_MESSAGE="${INFO} Check import order on python files ${DARK_GRAY}[*.py]${RESET}"
32 | task "isort --check-only" "$PY_MESSAGE" "$py_files"
33 | PY_MESSAGE="${INFO} Linting python files ${DARK_GRAY}[*.py]${RESET}"
34 | task flake8 "$PY_MESSAGE" .
35 | PY_MESSAGE="${INFO} Black python files ${DARK_GRAY}[*.py]${RESET}"
36 | task "black --check" "$PY_MESSAGE" .
37 |
--------------------------------------------------------------------------------
/run-checks.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -x
2 |
3 | ./run-checks-python.sh
4 | ./run-checks-node.sh
5 |
--------------------------------------------------------------------------------
/run-dev-server.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | WORKDIR=`dirname "$0"`
4 | PYTHON=`which python3.4`
5 |
6 | virtualenv -p "$PYTHON" env
7 | . env/bin/activate
8 | cd "$WORKDIR"
9 |
10 | pip3.4 install -r requirements.txt
11 |
12 | python manage.py migrate
13 | python manage.py collectstatic --noinput
14 | python manage.py runserver
--------------------------------------------------------------------------------
/run-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash -x
2 |
3 | PYTHON_FOLDERS='api bounca certificate_engine vuetifyforms x509_pki superuser_signup'
4 | BASEDIR=`dirname "$0"`/
5 | cd $BASEDIR
6 |
7 | . ./env/bin/activate
8 |
9 | BLUE='\033[1;34m'
10 | BRIGHT_RED='\033[1;31m'
11 | DARK_GRAY='\033[0;37m'
12 | RESET='\033[m'
13 | INFO="${BLUE}[INFO]${RESET}"
14 |
15 | function task() {
16 | printf "$2\n"
17 | # docker-compose start
18 | $1 &
19 | pid=$!
20 | wait $pid
21 |
22 | if [ $? == 0 ]; then
23 | echo -ne "\033[0K\r"
24 | # docker-compose stop
25 | else
26 | printf "${BRIGHT_RED}Please fix the above errors ${RESET}\n"
27 | # docker-compose stop
28 | exit 1
29 | fi
30 | }
31 |
32 | mypy .
33 |
34 | PY_MESSAGE="${INFO} Running unit tests${RESET}"
35 | task "coverage run --include bounca/\* --omit */env/*,*/venv/*,*/migrations/*,*/tests/* manage.py test" "$PY_MESSAGE"
36 | coverage report
37 | coverage xml
38 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [flake8]
2 | ignore = F405, W503
3 | max-line-length = 120
4 | exclude = */migrations/*.py,docs,env,out
5 | max-complexity = 10
6 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from typing import List
2 |
3 | from setuptools import Command, find_packages, setup
4 | from setuptools.command.install import install as _install
5 | from setuptools.command.sdist import sdist as _sdist
6 |
7 | src_dir = "."
8 | packages = find_packages(src_dir)
9 |
10 |
11 | class FrontendBuilder(Command):
12 | user_options: List[str] = []
13 | description = "builds the frontend assets using NPM"
14 |
15 | def run(self):
16 | self.spawn(["npm", "install"])
17 |
18 | def initialize_options(self):
19 | pass
20 |
21 | def finalize_options(self):
22 | pass
23 |
24 |
25 | class sdist(_sdist):
26 | def run(self):
27 | """
28 | Runs the frontend command *before* packaging everything.
29 | """
30 | self.run_command("frontend")
31 | _sdist.run(self)
32 |
33 |
34 | class install(_install):
35 | def run(self):
36 | """
37 | Runs the frontend command *after* installing the python package(s).
38 | """
39 | _install.run(self)
40 | self.run_command("frontend")
41 |
42 |
43 | cmdclass = {
44 | "sdist": sdist,
45 | "install": install,
46 | "frontend": FrontendBuilder,
47 | }
48 |
49 | setup(
50 | name="bounca",
51 | version="0.4.5",
52 | cmdclass=cmdclass,
53 | entry_points={"console_scripts": ["djadmin = manage:main"]},
54 | scripts=["manage.py"],
55 | packages=packages,
56 | include_package_data=True,
57 | license="proprietary",
58 | classifiers=[
59 | "Private :: Do Not Upload",
60 | "License :: Other/Proprietary License",
61 | ],
62 | zip_safe=False,
63 | )
64 |
--------------------------------------------------------------------------------
/superuser_signup/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/superuser_signup/__init__.py
--------------------------------------------------------------------------------
/superuser_signup/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class SuperuserSignupConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "superuser_signup"
7 |
--------------------------------------------------------------------------------
/superuser_signup/forms.py:
--------------------------------------------------------------------------------
1 | from allauth.account.forms import SignupForm
2 |
3 |
4 | class SuperUserSignupForm(SignupForm):
5 | def save(self, request):
6 | user = super(SuperUserSignupForm, self).save(request)
7 | user.is_staff = True
8 | user.is_superuser = True
9 | user.save()
10 | return user
11 |
--------------------------------------------------------------------------------
/superuser_signup/views.py:
--------------------------------------------------------------------------------
1 | from allauth.account.utils import complete_signup
2 | from allauth.account.views import SignupView
3 | from allauth.core.exceptions import ImmediateHttpResponse
4 | from django.contrib.auth.models import User
5 | from django.http import HttpResponseNotFound
6 | from django.urls import reverse_lazy
7 | from django.utils.translation import gettext_lazy as _
8 |
9 | from superuser_signup.forms import SuperUserSignupForm
10 |
11 |
12 | class CreateSuperUserView(SignupView):
13 | form_class = SuperUserSignupForm
14 | success_url = reverse_lazy("admin:index")
15 |
16 | def dispatch(self, request, *args, **kwargs):
17 | if User.objects.exists():
18 | return HttpResponseNotFound()
19 | return super(SignupView, self).dispatch(request, args, kwargs)
20 |
21 | def get_context_data(self, **kwargs):
22 | ret = super(CreateSuperUserView, self).get_context_data(**kwargs)
23 | ret.update({"title": _("Register Super User")})
24 | return ret
25 |
26 | def form_valid(self, form):
27 | # no email verification required
28 | self.user = form.save(self.request)
29 | try:
30 | return complete_signup(
31 | self.request,
32 | self.user,
33 | "none",
34 | self.get_success_url(),
35 | )
36 | except ImmediateHttpResponse as e:
37 | return e.response
38 |
--------------------------------------------------------------------------------
/vuetifyforms/README.md:
--------------------------------------------------------------------------------
1 | vee-validate3 does not implement all the rules offered by vee-validate2.
2 | You can add these rules after importing ValidationProvider:
3 |
4 | ```angular2html
5 | /* vee-validate config */
6 | setInteractionMode('eager');
7 | Vue.component('extend', extend);
8 | Vue.component('ValidationObserver', ValidationObserver);
9 | Vue.component('ValidationProvider', ValidationProvider);
10 |
11 | // install rules and localization
12 | Object.keys(rules).forEach((rule) => {
13 | extend(rule, rules[rule]);
14 | });
15 | extend('url', {
16 | validate(value) {
17 | const pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
18 | '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
19 | '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
20 | '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
21 | '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
22 | '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
23 | return pattern.test(value);
24 | },
25 | message: 'Please enter a valid URL',
26 | });
27 | localize('en', en);
28 | /* vee-validate config */
29 | ```
30 |
--------------------------------------------------------------------------------
/vuetifyforms/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/vuetifyforms/__init__.py
--------------------------------------------------------------------------------
/vuetifyforms/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class VuetifyformsConfig(AppConfig):
5 | name = "vuetifyforms"
6 |
--------------------------------------------------------------------------------
/vuetifyforms/management/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/vuetifyforms/management/commands/__init__.py
--------------------------------------------------------------------------------
/vuetifyforms/management/commands/generate_forms.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from crispy_forms.utils import render_crispy_form
4 | from django.conf import settings
5 | from django.core.management.base import BaseCommand
6 |
7 | from vuetifyforms.vue import VuetifyFormMixin
8 |
9 |
10 | class Command(BaseCommand):
11 | help = "Generate vuetify forms "
12 |
13 | def generate_form(self, form):
14 | self.stdout.write(f"Generating form {form.__name__}, writing to file {form.vue_file}")
15 | html_form = render_crispy_form(form, context={"form": form})
16 | full_path = os.path.join(settings.BASE_DIR, form.vue_file)
17 | with open(full_path, "w") as f:
18 | f.write(html_form)
19 |
20 | def generate_forms(self):
21 | forms = VuetifyFormMixin.get_subclasses()
22 | for form in forms:
23 | self.generate_form(form)
24 |
25 | def handle(self, *args, **options):
26 | self.stdout.write("Generating vuetify forms")
27 | self.generate_forms()
28 | self.stdout.write(self.style.SUCCESS("Successfully generated forms"))
29 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/display_form.html:
--------------------------------------------------------------------------------
1 | {% if form.form_html %}
2 | {% if include_media %}{{ form.media }}{% endif %}
3 | {{ form.form_html }}
4 | {% else %}
5 | {% include "vuetify/uni_form.html" %}
6 | {% endif %}
7 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/field.html:
--------------------------------------------------------------------------------
1 | {% load crispy_forms_vuetify %}
2 | {% load crispy_forms_field %}
3 |
4 | {% if field.is_hidden %}
5 | {{ field }}
6 | {% else %}
7 | {% if field.help_text %}
8 |
9 |
10 | {% endif %}
11 |
13 | {% if field|is_select %}
14 |
21 | {% elif field|is_array %}
22 |
28 | {% else %}
29 | ({{ field.name }}_visible = !{{ field.name }}_visible)"
36 | :type="{{ field.name }}_visible ? 'text' : 'password' "
37 | {% else %}
38 | type="{{ field.widget_type }}"
39 | {% endif %}
40 | {% if field.field.required %}required{% endif %}
41 | {{ flat_attrs|safe }}
42 | {% if field.help_text %}
43 | v-bind="attrs"
44 | v-on="on"
45 | {% endif %}
46 | >
47 | {% endif %}
48 |
49 |
50 |
51 | {% if field.help_text %}
52 |
53 | {{ field.help_text|safe }}
54 |
55 | {% endif %}
56 |
57 | {% endif %}
58 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/baseinput.html:
--------------------------------------------------------------------------------
1 |
4 | {{ input.value }}
5 |
6 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/buttonholder.html:
--------------------------------------------------------------------------------
1 |
2 | {{ fields_output|safe }}
3 |
4 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/column.html:
--------------------------------------------------------------------------------
1 |
2 | {{ fields|safe }}
3 |
4 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/fieldset.html:
--------------------------------------------------------------------------------
1 |
2 | {% if legend %}{{ legend|safe }}{% endif %}
3 | {{ fields|safe }}
4 |
5 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/flex.html:
--------------------------------------------------------------------------------
1 |
2 | {{ fields|safe }}
3 |
4 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/row.html:
--------------------------------------------------------------------------------
1 |
2 | {{ fields|safe }}
3 |
4 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/layout/spacer.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/script/default.js:
--------------------------------------------------------------------------------
1 | {% load crispy_forms_vuetify %}
2 | {% include "vuetify/script/imports.js" %}
3 |
4 | function initialState (){
5 | const data = {% make_data_object form %};
6 | {{ form.vue_extra_initial_statements|safe }}
7 | return data;
8 | }
9 |
10 | export default {
11 | name: '{{ form.form_component_name }}',
12 | props: [{% for prop in form.vue_props %}'{{ prop }}'{% if not forloop.last %},{% endif %}{% endfor %}],
13 | data() {
14 | return initialState();
15 | },
16 | watch: {
17 | {% for watch in form.vue_watchers %}
18 | {{ watch|safe }},
19 | {% endfor %}
20 | },
21 | mounted() {
22 | {{ form.vue_mounted|safe }}
23 | },
24 | {% include "vuetify/script/methods.js" %}
25 | };
26 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/script/imports.js:
--------------------------------------------------------------------------------
1 | {% for name, path in form.vue_imports %}
2 | import {{ name|safe }} from '{{ path|safe }}';
3 | {% endfor %}
4 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/script/methods.js:
--------------------------------------------------------------------------------
1 | methods: {
2 | resetForm: function (){
3 | Object.assign(this.$data, initialState());
4 | this.$refs.form.reset();
5 | {{ form.vue_extra_init_rules|safe }}
6 | },
7 | {% for method in form.vue_methods %}
8 | {{ method|safe }},
9 | {% endfor %}
10 | },
11 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/uni_form.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 | {% verbatim %}{{error}}{% endverbatim %}
15 |
16 |
17 | {% for field in form %}
18 | {% include field_template %}
19 | {% endfor %}
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/vuetifyforms/templates/vuetify/whole_uni_form.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ form.form_title }}
7 |
8 |
9 |
10 |
11 |
12 |
20 | {% verbatim %}{{error}}{% endverbatim %}
21 |
22 |
23 |
24 | {% include "vuetify/display_form.html" %}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
38 |
--------------------------------------------------------------------------------
/vuetifyforms/templatetags/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/vuetifyforms/templatetags/__init__.py
--------------------------------------------------------------------------------
/vuetifyforms/views.py:
--------------------------------------------------------------------------------
1 | from rest_framework import exceptions
2 | from rest_framework.views import exception_handler as drf_exception_handler
3 |
4 |
5 | def _flatten_vue_validation(val, key_prefix=""):
6 | if isinstance(val, list):
7 | return [_flatten_vue_validation(x) for x in val]
8 | elif isinstance(val, dict):
9 | res = {}
10 | for k in val:
11 | v = _flatten_vue_validation(val[k], key_prefix=f"{k}__")
12 | if isinstance(v, dict):
13 | res.update(v)
14 | else:
15 | res[f"{key_prefix}{k}"] = val[k]
16 | return res
17 | else:
18 | return val
19 |
20 |
21 | def vue_exception_handler(exc, context):
22 | """
23 | Flattens the 400 validation responses so it can be handled by vue.
24 |
25 | Other error are processed by the default rest_framework.views.exception_handler
26 | """
27 | if isinstance(exc, exceptions.APIException) and isinstance(exc.detail, (list, dict)):
28 | exc.detail = _flatten_vue_validation(exc.detail)
29 |
30 | return drf_exception_handler(exc, context)
31 |
--------------------------------------------------------------------------------
/vuetifyforms/vue.py:
--------------------------------------------------------------------------------
1 | class VuetifyFormMixin(object):
2 | field_css_classes = "form-group has-feedback"
3 | widget_css_classes = "form-control"
4 | form_error_css_classes = "djng-form-errors"
5 | field_error_css_classes = "djng-form-control-feedback djng-field-errors"
6 | label_css_classes = "control-label"
7 |
8 | @classmethod
9 | def get_subclasses(cls):
10 | for subclass in cls.__subclasses__():
11 | yield from subclass.get_subclasses()
12 | yield subclass
13 |
14 | def as_vuetify(self):
15 | """
16 | Returns this form rendered as HTML with s for each form field.
17 | """
18 | # wrap non-field-errors into
-element to prevent re-boxing
19 | error_row = '
%s
'
20 | div_element = self._html_output(
21 | normal_row="
%(label)s%(field)s%(help_text)s%(errors)s
",
22 | error_row=error_row,
23 | row_ender="
",
24 | help_text_html='
%s',
25 | errors_on_separate_row=False,
26 | )
27 | return div_element
28 |
--------------------------------------------------------------------------------
/x509_pki/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/x509_pki/__init__.py
--------------------------------------------------------------------------------
/x509_pki/apps.py:
--------------------------------------------------------------------------------
1 | """App name"""
2 |
3 | from django.apps import AppConfig
4 |
5 |
6 | class X509PkiConfig(AppConfig):
7 | name = "x509_pki"
8 |
--------------------------------------------------------------------------------
/x509_pki/management/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/x509_pki/management/__init__.py
--------------------------------------------------------------------------------
/x509_pki/management/commands/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/x509_pki/management/commands/__init__.py
--------------------------------------------------------------------------------
/x509_pki/migrations/0002_keystore_fingerprint.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-04-18 08:22
2 |
3 | from django.db import migrations, models
4 |
5 | from certificate_engine.ssl.info import get_certificate_fingerprint
6 |
7 |
8 | def set_my_defaults(apps, schema_editor):
9 | Keystore = apps.get_model('x509_pki', 'keystore')
10 | for keystore in Keystore.objects.all().iterator():
11 | keystore.fingerprint = get_certificate_fingerprint(keystore.crt)
12 | keystore.save()
13 |
14 |
15 | def reverse_func(apps, schema_editor):
16 | pass # code for reverting migration, if any
17 |
18 |
19 | class Migration(migrations.Migration):
20 |
21 | dependencies = [
22 | ('x509_pki', '0001_squashed_0015_keystore_p12'),
23 | ]
24 |
25 | operations = [
26 | migrations.AddField(
27 | model_name='keystore',
28 | name='fingerprint',
29 | field=models.TextField(null=True, verbose_name='SHA1 Fingerprint of Certificate'),
30 | preserve_default=False,
31 | ),
32 | migrations.RunPython(set_my_defaults, reverse_func),
33 | migrations.AlterField(
34 | model_name='keystore',
35 | name='fingerprint',
36 | field=models.TextField(),
37 | ),
38 | ]
39 |
40 |
--------------------------------------------------------------------------------
/x509_pki/migrations/0003_alter_keystore_fingerprint.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-05-03 20:49
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('x509_pki', '0002_keystore_fingerprint'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='keystore',
15 | name='fingerprint',
16 | field=models.TextField(verbose_name='SHA1 Fingerprint of Certificate'),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/x509_pki/migrations/0004_alter_certificate_type.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.0.4 on 2022-05-03 20:53
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = [
9 | ('x509_pki', '0003_alter_keystore_fingerprint'),
10 | ]
11 |
12 | operations = [
13 | migrations.AlterField(
14 | model_name='certificate',
15 | name='type',
16 | field=models.CharField(choices=[('R', 'Root CA Certificate'), ('I', 'Intermediate CA Certificate'), ('S', 'Server Certificate'), ('C', 'Client Certificate'), ('D', 'Code Signing Certificate'), ('O', 'OCSP Signing Certificate')], max_length=1),
17 | ),
18 | ]
19 |
--------------------------------------------------------------------------------
/x509_pki/migrations/0005_alter_certificate_crl_distribution_url.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.1.5 on 2023-02-05 14:38
2 |
3 | import django.core.validators
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | dependencies = [
10 | ("x509_pki", "0004_alter_certificate_type"),
11 | ]
12 |
13 | operations = [
14 | migrations.AlterField(
15 | model_name="certificate",
16 | name="crl_distribution_url",
17 | field=models.URLField(
18 | blank=True,
19 | help_text="Base URL for certificate revocation list (CRL)",
20 | null=True,
21 | validators=[
22 | django.core.validators.RegexValidator("[^\\/]\\.crl$", "CRL url should end with
.crl")
23 | ],
24 | verbose_name="CRL distribution url",
25 | ),
26 | ),
27 | ]
28 |
--------------------------------------------------------------------------------
/x509_pki/migrations/0006_keystore_p12_legacy.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 4.2.9 on 2024-01-26 08:58
2 |
3 | from django.db import migrations, models
4 |
5 |
6 | class Migration(migrations.Migration):
7 | dependencies = [
8 | ("x509_pki", "0005_alter_certificate_crl_distribution_url"),
9 | ]
10 |
11 | operations = [
12 | migrations.AddField(
13 | model_name="keystore",
14 | name="p12_legacy",
15 | field=models.BinaryField(
16 | blank=True,
17 | default=None,
18 | null=True,
19 | verbose_name="Serialized PKCS 12 package with key and certificate sha1 for legacy support",
20 | ),
21 | ),
22 | ]
23 |
--------------------------------------------------------------------------------
/x509_pki/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/x509_pki/migrations/__init__.py
--------------------------------------------------------------------------------
/x509_pki/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/repleo/bounca/fdd52ea3d16173040152a19a0dd61287c01ee674/x509_pki/tests/__init__.py
--------------------------------------------------------------------------------
/x509_pki/tests/test_factories.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | from django.test import TestCase
3 |
4 | from x509_pki.tests.factories import CertificateFactory, DistinguishedNameFactory, UserFactory
5 |
6 |
7 | class FactoriesTest(TestCase):
8 | """
9 | Very simple tests to ensure the factories work as expected.
10 | """
11 |
12 | def test_user_factory(self):
13 | user = UserFactory()
14 | self.assertIsNotNone(user.username)
15 | self.assertIsNotNone(user.password)
16 | self.assertIsNotNone(user.first_name)
17 | self.assertIsNotNone(user.last_name)
18 | self.assertFalse(user.is_superuser)
19 | self.assertFalse(user.is_staff)
20 | self.assertTrue(user.is_active)
21 |
22 | def test_distinguished_name_factory(self):
23 | dn = DistinguishedNameFactory()
24 | self.assertIsNotNone(dn.countryName)
25 | self.assertIsNotNone(dn.stateOrProvinceName)
26 | self.assertIsNotNone(dn.localityName)
27 | self.assertIsNotNone(dn.organizationName)
28 | self.assertIsNotNone(dn.organizationalUnitName)
29 | self.assertIsNotNone(dn.emailAddress)
30 | self.assertIsNotNone(dn.commonName)
31 | self.assertIsNotNone(dn.subjectAltNames)
32 |
33 | def test_certificate_factory(self):
34 | cert = CertificateFactory()
35 | self.assertIsNotNone(cert.type)
36 | self.assertIsNotNone(cert.name)
37 | self.assertIsNotNone(cert.dn)
38 | self.assertIsNone(cert.parent)
39 | self.assertIsNotNone(cert.crl_distribution_url)
40 | self.assertIsNotNone(cert.ocsp_distribution_host)
41 | self.assertIsNotNone(cert.owner)
42 | self.assertIsNotNone(cert.serial)
43 | self.assertIsNotNone(cert.created_at)
44 | self.assertIsNotNone(cert.expires_at)
45 | self.assertIsNone(cert.revoked_at)
46 | self.assertIsNotNone(cert.revoked_uuid)
47 |
--------------------------------------------------------------------------------