From 24de27a71427e0e7d339418dafa952443d37ae1e Mon Sep 17 00:00:00 2001 From: Godopu Date: Mon, 26 Dec 2022 04:36:19 +0000 Subject: [PATCH] deploy version 0.1 --- .gitignore | 3 +- config/authelia/configuration.yml | 916 +++++++++++++++++++++++++++++ config/authelia/db.sqlite3 | Bin 0 -> 278528 bytes config/authelia/users_database.yml | 36 ++ config/traefik/router.yaml | 71 +++ config/traefik/traefik.yaml | 65 ++ docker-compose.yaml | 51 +- webserver/router/auth.go | 9 +- webserver/router/reverse_proxy.go | 2 +- webserver/router/route.go | 2 +- 10 files changed, 1140 insertions(+), 15 deletions(-) create mode 100644 config/authelia/configuration.yml create mode 100644 config/authelia/db.sqlite3 create mode 100644 config/authelia/users_database.yml create mode 100644 config/traefik/router.yaml create mode 100644 config/traefik/traefik.yaml diff --git a/.gitignore b/.gitignore index a0b638f..c9464b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -iot-www/ \ No newline at end of file +iot-www/ +volumes/ \ No newline at end of file diff --git a/config/authelia/configuration.yml b/config/authelia/configuration.yml new file mode 100644 index 0000000..57857a4 --- /dev/null +++ b/config/authelia/configuration.yml @@ -0,0 +1,916 @@ +# yamllint disable rule:comments-indentation +--- +############################################################################### +# Authelia Configuration # +############################################################################### + +## Note: the container by default expects to find this file at /config/configuration.yml. + +## Certificates directory specifies where Authelia will load trusted certificates (public portion) from in addition to +## the system certificates store. +## They should be in base64 format, and have one of the following extensions: *.cer, *.crt, *.pem. +# certificates_directory: /config/certificates/ + +## The theme to display: light, dark, grey, auto. +theme: dark + +## The secret used to generate JWT tokens when validating user identity by email confirmation. JWT Secret can also be +## set using a secret: https://www.authelia.com/c/secrets +jwt_secret: mydwxdd-c2hbo6zcmab1mzj232zx4 + +## Default redirection URL +## +## If user tries to authenticate without any referer, Authelia does not know where to redirect the user to at the end +## of the authentication process. This parameter allows you to specify the default redirection URL Authelia will use +## in such a case. +## +## Note: this parameter is optional. If not provided, user won't be redirected upon successful authentication. +default_redirection_url: https://auth.godopu.net/authenticated + +## Set the default 2FA method for new users and for when a user has a preferred method configured that has been +## disabled. This setting must be a method that is enabled. +## Options are totp, webauthn, mobile_push. +default_2fa_method: "" + +## +## Server Configuration +## +server: + + ## The address to listen on. + host: 0.0.0.0 + + ## The port to listen on. + port: 9091 + + ## Set the single level path Authelia listens on. + ## Must be alphanumeric chars and should not contain any slashes. + path: "" + + ## Set the path on disk to Authelia assets. + ## Useful to allow overriding of specific static assets. + # asset_path: /config/assets/ + + ## Buffers usually should be configured to be the same value. + ## Explanation at https://www.authelia.com/c/server#buffer-sizes + ## Read buffer size adjusts the server's max incoming request size in bytes. + ## Write buffer size does the same for outgoing responses. + read_buffer_size: 4096 + write_buffer_size: 4096 + + ## Enables the pprof endpoint. + enable_pprof: false + + ## Enables the expvars endpoint. + enable_expvars: false + + ## Disables writing the health check vars to /app/.healthcheck.env which makes healthcheck.sh return exit code 0. + ## This is disabled by default if either /app/.healthcheck.env or /app/healthcheck.sh do not exist. + disable_healthcheck: false + + ## Authelia by default doesn't accept TLS communication on the server port. This section overrides this behaviour. + tls: + ## The path to the DER base64/PEM format private key. + key: "" + + ## The path to the DER base64/PEM format public certificate. + certificate: "" + + ## The list of certificates for client authentication. + client_certificates: [] + + ## Server headers configuration/customization. + headers: + + ## The CSP Template. Read the docs. + csp_template: "" + +## +## Log Configuration +## +log: + ## Level of verbosity for logs: info, debug, trace. + level: debug + + ## Format the logs are written as: json, text. + # format: json + + ## File path where the logs will be written. If not set logs are written to stdout. + # file_path: /config/authelia.log + + ## Whether to also log to stdout when a log_file_path is defined. + # keep_stdout: false + +## +## Telemetry Configuration +## +telemetry: + + ## + ## Metrics Configuration + ## + metrics: + ## Enable Metrics. + enabled: false + + ## The address to listen on for metrics. This should be on a different port to the main server.port value. + address: tcp://0.0.0.0:9959 + +## +## TOTP Configuration +## +## Parameters used for TOTP generation. +totp: + ## Disable TOTP. + disable: false + + ## The issuer name displayed in the Authenticator application of your choice. + issuer: godopu.net + + ## The TOTP algorithm to use. + ## It is CRITICAL you read the documentation before changing this option: + ## https://www.authelia.com/c/totp#algorithm + algorithm: sha1 + + ## The number of digits a user has to input. Must either be 6 or 8. + ## Changing this option only affects newly generated TOTP configurations. + ## It is CRITICAL you read the documentation before changing this option: + ## https://www.authelia.com/c/totp#digits + digits: 6 + + ## The period in seconds a one-time password is valid for. + ## Changing this option only affects newly generated TOTP configurations. + period: 30 + + ## The skew controls number of one-time passwords either side of the current one that are valid. + ## Warning: before changing skew read the docs link below. + skew: 1 + ## See: https://www.authelia.com/c/totp#input-validation to read + ## the documentation. + + ## The size of the generated shared secrets. Default is 32 and is sufficient in most use cases, minimum is 20. + secret_size: 32 + +## +## WebAuthn Configuration +## +## Parameters used for WebAuthn. +webauthn: + ## Disable Webauthn. + disable: false + + ## Adjust the interaction timeout for Webauthn dialogues. + timeout: 60s + + ## The display name the browser should show the user for when using Webauthn to login/register. + display_name: Authelia + + ## Conveyance preference controls if we collect the attestation statement including the AAGUID from the device. + ## Options are none, indirect, direct. + attestation_conveyance_preference: indirect + + ## User verification controls if the user must make a gesture or action to confirm they are present. + ## Options are required, preferred, discouraged. + user_verification: preferred + +## +## Duo Push API Configuration +## +## Parameters used to contact the Duo API. Those are generated when you protect an application of type +## "Partner Auth API" in the management panel. +duo_api: + disable: false + hostname: api-123456789.example.com + integration_key: ABCDEF + ## Secret can also be set using a secret: https://www.authelia.com/c/secrets + secret_key: 1234567890abcdefghifjkl + enable_self_enrollment: false + +## +## NTP Configuration +## +## This is used to validate the servers time is accurate enough to validate TOTP. +ntp: + ## NTP server address. + address: "time.cloudflare.com:123" + + ## NTP version. + version: 4 + + ## Maximum allowed time offset between the host and the NTP server. + max_desync: 3s + + ## Disables the NTP check on startup entirely. This means Authelia will not contact a remote service at all if you + ## set this to true, and can operate in a truly offline mode. + disable_startup_check: false + + ## The default of false will prevent startup only if we can contact the NTP server and the time is out of sync with + ## the NTP server more than the configured max_desync. If you set this to true, an error will be logged but startup + ## will continue regardless of results. + disable_failure: false + +## +## Authentication Backend Provider Configuration +## +## Used for verifying user passwords and retrieve information such as email address and groups users belong to. +## +## The available providers are: `file`, `ldap`. You must use only one of these providers. +authentication_backend: + + # ## Password Reset Options. + # password_reset: + # ## Disable both the HTML element and the API for reset password functionality. + # disable: false + + # ## External reset password url that redirects the user to an external reset portal. This disables the internal reset + # ## functionality. + # custom_url: "" + + # ## The amount of time to wait before we refresh data from the authentication backend. Uses duration notation. + # ## To disable this feature set it to 'disable', this will slightly reduce security because for Authelia, users will + # ## always belong to groups they belonged to at the time of login even if they have been removed from them in LDAP. + # ## To force update on every request you can set this to '0' or 'always', this will increase processor demand. + # ## See the below documentation for more information. + # ## Duration Notation docs: https://www.authelia.com/c/common#duration-notation-format + # ## Refresh Interval docs: https://www.authelia.com/c/1fa#refresh-interval + # refresh_interval: 5m + + # ## + # ## LDAP (Authentication Provider) + # ## + # ## This is the recommended Authentication Provider in production + # ## because it allows Authelia to offload the stateful operations + # ## onto the LDAP service. + # ldap: + # ## The LDAP implementation, this affects elements like the attribute utilised for resetting a password. + # ## Acceptable options are as follows: + # ## - 'activedirectory' - For Microsoft Active Directory. + # ## - 'custom' - For custom specifications of attributes and filters. + # ## This currently defaults to 'custom' to maintain existing behaviour. + # ## + # ## Depending on the option here certain other values in this section have a default value, notably all of the + # ## attribute mappings have a default value that this config overrides, you can read more about these default values + # ## at https://www.authelia.com/c/ldap#defaults + # implementation: custom + + # ## The url to the ldap server. Format: ://
[:]. + # ## Scheme can be ldap or ldaps in the format (port optional). + # url: ldap://127.0.0.1 + + # ## The dial timeout for LDAP. + # timeout: 5s + + # ## Use StartTLS with the LDAP connection. + # start_tls: false + + # tls: + # ## Server Name for certificate validation (in case it's not set correctly in the URL). + # # server_name: ldap.example.com + + # ## Skip verifying the server certificate (to allow a self-signed certificate). + # ## In preference to setting this we strongly recommend you add the public portion of the certificate to the + # ## certificates directory which is defined by the `certificates_directory` option at the top of the config. + # skip_verify: false + + # ## Minimum TLS version for either Secure LDAP or LDAP StartTLS. + # minimum_version: TLS1.2 + + # ## The distinguished name of the container searched for objects in the directory information tree. + # ## See also: additional_users_dn, additional_groups_dn. + # base_dn: dc=example,dc=com + + # ## The attribute holding the username of the user. This attribute is used to populate the username in the session + # ## information. It was introduced due to #561 to handle case insensitive search queries. For you information, + # ## Microsoft Active Directory usually uses 'sAMAccountName' and OpenLDAP usually uses 'uid'. Beware that this + # ## attribute holds the unique identifiers for the users binding the user and the configuration stored in database. + # ## Therefore only single value attributes are allowed and the value must never be changed once attributed to a user + # ## otherwise it would break the configuration for that user. Technically, non-unique attributes like 'mail' can also + # ## be used but we don't recommend using them, we instead advise to use the attributes mentioned above + # ## (sAMAccountName and uid) to follow https://www.ietf.org/rfc/rfc2307.txt. + # # username_attribute: uid + + # ## The additional_users_dn is prefixed to base_dn and delimited by a comma when searching for users. + # ## i.e. with this set to OU=Users and base_dn set to DC=a,DC=com; OU=Users,DC=a,DC=com is searched for users. + # additional_users_dn: ou=users + + # ## The users filter used in search queries to find the user profile based on input filled in login form. + # ## Various placeholders are available in the user filter which you can read about in the documentation which can + # ## be found at: https://www.authelia.com/c/ldap#users-filter-replacements + # ## + # ## Recommended settings are as follows: + # ## - Microsoft Active Directory: (&({username_attribute}={input})(objectCategory=person)(objectClass=user)) + # ## - OpenLDAP: + # ## - (&({username_attribute}={input})(objectClass=person)) + # ## - (&({username_attribute}={input})(objectClass=inetOrgPerson)) + # ## + # ## To allow sign in both with username and email, one can use a filter like + # ## (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person)) + # users_filter: (&({username_attribute}={input})(objectClass=person)) + + # ## The additional_groups_dn is prefixed to base_dn and delimited by a comma when searching for groups. + # ## i.e. with this set to OU=Groups and base_dn set to DC=a,DC=com; OU=Groups,DC=a,DC=com is searched for groups. + # additional_groups_dn: ou=groups + + # ## The groups filter used in search queries to find the groups based on relevant authenticated user. + # ## Various placeholders are available in the groups filter which you can read about in the documentation which can + # ## be found at: https://www.authelia.com/c/ldap#groups-filter-replacements + # ## + # ## If your groups use the `groupOfUniqueNames` structure use this instead: + # ## (&(uniqueMember={dn})(objectClass=groupOfUniqueNames)) + # groups_filter: (&(member={dn})(objectClass=groupOfNames)) + + # ## The attribute holding the name of the group. + # # group_name_attribute: cn + + # ## The attribute holding the mail address of the user. If multiple email addresses are defined for a user, only the + # ## first one returned by the LDAP server is used. + # # mail_attribute: mail + + # ## The attribute holding the display name of the user. This will be used to greet an authenticated user. + # # display_name_attribute: displayName + + # ## Follow referrals returned by the server. + # ## This is especially useful for environments where read-only servers exist. Only implemented for write operations. + # permit_referrals: false + + # ## The username and password of the admin user. + # user: cn=admin,dc=example,dc=com + # ## Password can also be set using a secret: https://www.authelia.com/c/secrets + # password: password + + ## + ## File (Authentication Provider) + ## + ## With this backend, the users database is stored in a file which is updated when users reset their passwords. + ## Therefore, this backend is meant to be used in a dev environment and not in production since it prevents Authelia + ## to be scaled to more than one instance. The options under 'password' have sane defaults, and as it has security + ## implications it is highly recommended you leave the default values. Before considering changing these settings + ## please read the docs page below: + ## https://www.authelia.com/r/passwords#tuning + ## + ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness + ## + file: + path: /config/users_database.yml + password: + algorithm: argon2id + iterations: 1 + key_length: 32 + salt_length: 16 + memory: 1024 + parallelism: 8 + +## +## Password Policy Configuration. +## +password_policy: + + ## The standard policy allows you to tune individual settings manually. + standard: + enabled: false + + ## Require a minimum length for passwords. + min_length: 8 + + ## Require a maximum length for passwords. + max_length: 0 + + ## Require uppercase characters. + require_uppercase: true + + ## Require lowercase characters. + require_lowercase: true + + ## Require numeric characters. + require_number: true + + ## Require special characters. + require_special: true + + ## zxcvbn is a well known and used password strength algorithm. It does not have tunable settings. + zxcvbn: + enabled: false + + ## Configures the minimum score allowed. + min_score: 3 + +## +## Access Control Configuration +## +## Access control is a list of rules defining the authorizations applied for one resource to users or group of users. +## +## If 'access_control' is not defined, ACL rules are disabled and the 'bypass' rule is applied, i.e., access is allowed +## to anyone. Otherwise restrictions follow the rules defined. +## +## Note: One can use the wildcard * to match any subdomain. +## It must stand at the beginning of the pattern. (example: *.mydomain.com) +## +## Note: You must put patterns containing wildcards between simple quotes for the YAML to be syntactically correct. +## +## Definition: A 'rule' is an object with the following keys: 'domain', 'subject', 'policy' and 'resources'. +## +## - 'domain' defines which domain or set of domains the rule applies to. +## +## - 'subject' defines the subject to apply authorizations to. This parameter is optional and matching any user if not +## provided. If provided, the parameter represents either a user or a group. It should be of the form +## 'user:' or 'group:'. +## +## - 'policy' is the policy to apply to resources. It must be either 'bypass', 'one_factor', 'two_factor' or 'deny'. +## +## - 'resources' is a list of regular expressions that matches a set of resources to apply the policy to. This parameter +## is optional and matches any resource if not provided. +## +## Note: the order of the rules is important. The first policy matching (domain, resource, subject) applies. +access_control: + ## Default policy can either be 'bypass', 'one_factor', 'two_factor' or 'deny'. It is the policy applied to any + ## resource if there is no policy to be applied to the user. + default_policy: deny + + networks: + - name: internal + networks: + - 10.10.0.0/16 + - 192.168.2.0/24 + - name: VPN + networks: 10.9.0.0/16 + + rules: + ## Rules applied to everyone + - domain: 'auth.godopu.net' + policy: bypass + + ## Domain Regex examples. Generally we recommend just using a standard domain. + # - domain_regex: '^(?P\w+)\.example\.com$' + # policy: one_factor + # - domain_regex: '^(?P\w+)\.example\.com$' + # policy: one_factor + # - domain_regex: + # - '^appgroup-.*\.example\.com$' + # - '^appgroup2-.*\.example\.com$' + # policy: one_factor + # - domain_regex: '^.*\.example\.com$' + # policy: two_factor + + - domain: 'iot.knu.ac.kr' + policy: one_factor + - domain: 'protocol.knu.ac.kr' + policy: one_factor + ## Network based rule, if not provided any network matches. + # networks: + # - internal + # - VPN + # - 192.168.1.0/24 + # - 10.0.0.1 + + # - domain: + # - 'auth.godopu.com' + # - 'auth.godopu.com' + # policy: two_factor + + # - domain: 'singlefactor.example.com' + # policy: one_factor + + # ## Rules applied to 'admins' group + # - domain: 'mx2.mail.example.com' + # subject: 'group:admins' + # policy: deny + + # - domain: '*.example.com' + # subject: + # - 'group:admins' + # - 'group:moderators' + # policy: two_factor + + # ## Rules applied to 'dev' group + # - domain: 'dev.example.com' + # resources: + # - '^/groups/dev/.*$' + # subject: 'group:dev' + # policy: two_factor + + # ## Rules applied to user 'john' + # - domain: 'dev.example.com' + # resources: + # - '^/users/john/.*$' + # subject: 'user:john' + # policy: two_factor + + # ## Rules applied to user 'harry' + # - domain: 'dev.example.com' + # resources: + # - '^/users/harry/.*$' + # subject: 'user:harry' + # policy: two_factor + + # ## Rules applied to user 'bob' + # - domain: '*.mail.example.com' + # subject: 'user:bob' + # policy: two_factor + # - domain: 'dev.example.com' + # resources: + # - '^/users/bob/.*$' + # subject: 'user:bob' + # policy: two_factor + +## +## Session Provider Configuration +## +## The session cookies identify the user once logged in. +## The available providers are: `memory`, `redis`. Memory is the provider unless redis is defined. +session: + ## The name of the session cookie. + name: authelia_session + + ## The domain to protect. + ## Note: the authenticator must also be in that domain. + ## If empty, the cookie is restricted to the subdomain of the issuer. + domain: godopu.net + + ## Sets the Cookie SameSite value. Possible options are none, lax, or strict. + ## Please read https://www.authelia.com/c/session#same_site + same_site: lax + + ## The secret to encrypt the session data. This is only used with Redis / Redis Sentinel. + ## Secret can also be set using a secret: https://www.authelia.com/c/secrets + secret: insecure_session_secret + + ## The value for expiration, inactivity, and remember_me_duration are in seconds or the duration notation format. + ## See: https://www.authelia.com/c/common#duration-notation-format + ## All three of these values affect the cookie/session validity period. Longer periods are considered less secure + ## because a stolen cookie will last longer giving attackers more time to spy or attack. + + ## The time before the cookie expires and the session is destroyed if remember me IS NOT selected. + expiration: 1h + + ## The inactivity time before the session is reset. If expiration is set to 1h, and this is set to 5m, if the user + ## does not select the remember me option their session will get destroyed after 1h, or after 5m since the last time + ## Authelia detected user activity. + inactivity: 5m + + ## The time before the cookie expires and the session is destroyed if remember me IS selected. + ## Value of -1 disables remember me. + remember_me_duration: 1M + + ## + ## Redis Provider + ## + ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness + ## + # redis: + # host: outline-redis + # port: 6379 + # ## Use a unix socket instead + # # host: /var/run/redis/redis.sock + + # ## Username used for redis authentication. This is optional and a new feature in redis 6.0. + # # username: authelia + + # ## Password can also be set using a secret: https://www.authelia.com/c/secrets + # password: authelia + + # ## This is the Redis DB Index https://redis.io/commands/select (sometimes referred to as database number, DB, etc). + # database_index: 0 + + # ## The maximum number of concurrent active connections to Redis. + # maximum_active_connections: 8 + + # ## The target number of idle connections to have open ready for work. Useful when opening connections is slow. + # minimum_idle_connections: 0 + + ## The Redis TLS configuration. If defined will require a TLS connection to the Redis instance(s). + # tls: + ## Server Name for certificate validation (in case you are using the IP or non-FQDN in the host option). + # server_name: myredis.example.com + + ## Skip verifying the server certificate (to allow a self-signed certificate). + ## In preference to setting this we strongly recommend you add the public portion of the certificate to the + ## certificates directory which is defined by the `certificates_directory` option at the top of the config. + # skip_verify: false + + ## Minimum TLS version for the connection. + # minimum_version: TLS1.2 + + ## The Redis HA configuration options. + ## This provides specific options to Redis Sentinel, sentinel_name must be defined (Master Name). + # high_availability: + ## Sentinel Name / Master Name. + # sentinel_name: mysentinel + + ## Specific username for Redis Sentinel. The node username and password is configured above. + # sentinel_username: sentinel_specific_user + + ## Specific password for Redis Sentinel. The node username and password is configured above. + # sentinel_password: sentinel_specific_pass + + ## The additional nodes to pre-seed the redis provider with (for sentinel). + ## If the host in the above section is defined, it will be combined with this list to connect to sentinel. + ## For high availability to be used you must have either defined; the host above or at least one node below. + # nodes: + # - host: sentinel-node1 + # port: 6379 + # - host: sentinel-node2 + # port: 6379 + + ## Choose the host with the lowest latency. + # route_by_latency: false + + ## Choose the host randomly. + # route_randomly: false + +## +## Regulation Configuration +## +## This mechanism prevents attackers from brute forcing the first factor. It bans the user if too many attempts are made +## in a short period of time. +regulation: + ## The number of failed login attempts before user is banned. Set it to 0 to disable regulation. + max_retries: 3 + + ## The time range during which the user can attempt login before being banned. The user is banned if the + ## authentication failed 'max_retries' times in a 'find_time' seconds window. Find Time accepts duration notation. + ## See: https://www.authelia.com/c/common#duration-notation-format + find_time: 2m + + ## The length of time before a banned user can login again. Ban Time accepts duration notation. + ## See: https://www.authelia.com/c/common#duration-notation-format + ban_time: 5m + +## +## Storage Provider Configuration +## +## The available providers are: `local`, `mysql`, `postgres`. You must use one and only one of these providers. +storage: + ## The encryption key that is used to encrypt sensitive information in the database. Must be a string with a minimum + ## length of 20. Please see the docs if you configure this with an undesirable key and need to change it. + encryption_key: mydwxdd-c2hbo6zcmab1mzj232zx4 + + ## + ## Local (Storage Provider) + ## + ## This stores the data in a SQLite3 Database. + ## This is only recommended for lightweight non-stateful installations. + ## + ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness + ## + local: + path: /config/db.sqlite3 + + ## + ## MySQL / MariaDB (Storage Provider) + ## + # mysql: + # host: 127.0.0.1 + # port: 3306 + # database: authelia + # username: authelia + # ## Password can also be set using a secret: https://www.authelia.com/c/secrets + # password: mypassword + # timeout: 5s + + ## + ## PostgreSQL (Storage Provider) + ## + # postgres: + # host: 127.0.0.1 + # port: 5432 + # database: authelia + # schema: public + # username: authelia + # ## Password can also be set using a secret: https://www.authelia.com/c/secrets + # password: mypassword + # timeout: 5s + # ssl: + # mode: disable + # root_certificate: disable + # certificate: disable + # key: disable + +## +## Notification Provider +## +## Notifications are sent to users when they require a password reset, a Webauthn registration or a TOTP registration. +## The available providers are: filesystem, smtp. You must use only one of these providers. +notifier: + ## You can disable the notifier startup check by setting this to true. + disable_startup_check: false + + ## + ## File System (Notification Provider) + ## + ## Important: Kubernetes (or HA) users must read https://www.authelia.com/t/statelessness + ## + # filesystem: + # filename: /config/notification.txt + + ## + ## SMTP (Notification Provider) + ## + ## Use a SMTP server for sending notifications. Authelia uses the PLAIN or LOGIN methods to authenticate. + ## [Security] By default Authelia will: + ## - force all SMTP connections over TLS including unauthenticated connections + ## - use the disable_require_tls boolean value to disable this requirement + ## (only works for unauthenticated connections) + ## - validate the SMTP server x509 certificate during the TLS handshake against the hosts trusted certificates + ## (configure in tls section) + smtp: + username: godopu16@gmail.com #your email address + password: cdjdagxrmywcbaqf #your email password + host: smtp.gmail.com #email smtp server + port: 587 #email smtp port + sender: godopu16@gmail.com + identifier: localhost + subject: "[Authelia] {title}" #email subject + startup_check_address: godopu16@gmail.com + disable_require_tls: false + disable_html_emails: false +## +## Identity Providers +## +identity_providers: + + ## + ## OpenID Connect (Identity Provider) + ## + ## It's recommended you read the documentation before configuration of this section: + ## https://www.authelia.com/c/oidc + oidc: + # The hmac_secret is used to sign OAuth2 tokens (authorization code, access tokens and refresh tokens). + # HMAC Secret can also be set using a secret: https://www.authelia.com/c/secrets + hmac_secret: mydwxdd-c2hbo6zcmab1mzj232zx4 + + # The issuer_private_key is used to sign the JWT forged by OpenID Connect. + # Issuer Private Key can also be set using a secret: https://www.authelia.com/c/secrets + issuer_private_key: | + -----BEGIN RSA PRIVATE KEY----- + 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 + -----END RSA PRIVATE KEY----- + + # The lifespans configure the expiration for these token types. + access_token_lifespan: 1h + authorize_code_lifespan: 1m + id_token_lifespan: 1h + refresh_token_lifespan: 90m + + # Enables additional debug messages. + enable_client_debug_messages: false + clients: + - id: iot-ws + description: iot server + secret: mydwxdd-c2hbo6zcmab1mzj232zx4 + public: false + authorization_policy: one_factor + audience: [] + scopes: + - openid + - groups + - email + - profile + redirect_uris: + - https://iot.knu.ac.kr/auth/oidc.callback + grant_types: + - refresh_token + - authorization_code + response_types: + - code + response_modes: + - form_post + - query + - fragment + userinfo_signing_algorithm: none + # SECURITY NOTICE: It's not recommended changing this option and values below 8 are strongly discouraged. + minimum_parameter_entropy: 8 + + # SECURITY NOTICE: It's not recommended changing this option, and highly discouraged to have it set to 'never' + # for security reasons. + enforce_pkce: public_clients_only + + ## Cross-Origin Resource Sharing (CORS) settings. + # cors: + ## List of endpoints in addition to the metadata endpoints to permit cross-origin requests on. + # endpoints: + # - authorization + # - token + # - revocation + # - introspection + # - userinfo + + ## List of allowed origins. + ## Any origin with https is permitted unless this option is configured or the + ## allowed_origins_from_client_redirect_uris option is enabled. + # allowed_origins: + # - https://example.com + + ## Automatically adds the origin portion of all redirect URI's on all clients to the list of allowed_origins, + ## provided they have the scheme http or https and do not have the hostname of localhost. + # allowed_origins_from_client_redirect_uris: false + + ## Clients is a list of known clients and their configuration. + # clients: + # - + ## The ID is the OpenID Connect ClientID which is used to link an application to a configuration. + # id: myapp + + ## The description to show to users when they end up on the consent screen. Defaults to the ID above. + # description: My Application + + ## The client secret is a shared secret between Authelia and the consumer of this client. + # secret: this_is_a_secret + + ## Sector Identifiers are occasionally used to generate pairwise subject identifiers. In most cases this is not + ## necessary. Read the documentation for more information. + ## The subject identifier must be the host component of a URL, which is a domain name with an optional port. + # sector_identifier: example.com + + ## Sets the client to public. This should typically not be set, please see the documentation for usage. + # public: false + + ## The policy to require for this client; one_factor or two_factor. + # authorization_policy: two_factor + + ## By default users cannot remember pre-configured consents. Setting this value to a period of time using a + ## duration notation will enable users to remember consent for this client. The time configured is the amount + ## of time the pre-configured consent is valid for granting new authorizations to the user. + # pre_configured_consent_duration: + + ## Audience this client is allowed to request. + # audience: [] + + ## Scopes this client is allowed to request. + # scopes: + # - openid + # - groups + # - email + # - profile + + ## Redirect URI's specifies a list of valid case-sensitive callbacks for this client. + # redirect_uris: + # - https://oidc.example.com:8080/oauth2/callback + + ## Grant Types configures which grants this client can obtain. + ## It's not recommended to define this unless you know what you're doing. + # grant_types: + # - refresh_token + # - authorization_code + + ## Response Types configures which responses this client can be sent. + ## It's not recommended to define this unless you know what you're doing. + # response_types: + # - code + + ## Response Modes configures which response modes this client supports. + # response_modes: + # - form_post + # - query + # - fragment + + ## The algorithm used to sign userinfo endpoint responses for this client, either none or RS256. + # userinfo_signing_algorithm: none +... diff --git a/config/authelia/db.sqlite3 b/config/authelia/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..4ae78178da6e24799b124fc0bd2bbe9bf65f729b GIT binary patch literal 278528 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�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�#2VP<%S2o=;Gyb|As)&QX|skQ1HrdwqjYvOVx# zQ4jLVfJD)bNP8~ZlKJ?dB>PoLo7|+DF7vn7BR(jrLsa!%g7yicp|_@>|G zwULxk#2w1f2+6ecV;vH?I@qzevtxV#Z3%!JmJyb3-dFsNK#)}vpKzcRg^;@B3D)!u zh>cmos`g3m88m)H#@xtPr=+t&tZF*W4ovl~#mXX}Ex!cOb3Sbt<6y8o*7VmO)7UNv zx+rulf9@EGjk1-G`|*^J@&<5MssS(%k7P$rN@@-idXepYp{-uk-(tTg>nqsU|Fi$k zz#`80k12GR7r_W%1TX>^0gM1f03(1AzzF>R6o@eY`vTt>&3|o>$j2I~4iZ(@dZCH* z(bsbm*HVWdM7)q@R$2~%_8`bJxTdG5lDe~t0$k^x3lfO~g+)chMZo{$nxX<6&_z|| zqJ*6G#_Z7W0B!Qbvx1^es}EpV#d>#3;TAnT-}>f3*s=l2ppY2OI2r(Sem9^|BX3l1 znT=}oU72!`z>KCa>CLmDw!tjFt%An-CN(Ga#kmeX_SUk^H=*JCFXa?)y2VyuOJ&3C z0jsNYevA~KL$cvBt+>rq;0`E{RIuff4%%@Y_m5}8-F~K1#Sxk-A|z;`S7Mb8zhh{s z+M^S9-@erbQSvROe$`&yKeVGPqRUHSbF9{N2>c>&xAHi`)bESy%t(9Si|3cr^*aJF z?7Ij+KHZs>{YAe@)?7n3t!f1Tmv$>5)M$NFV_&>&XM9PFkN#rz0C>m?r}!{9TsdX_ zLlGS0WQH`dknj*V@{p{FutD5iMZahvZ+bx zP5JipaC!9L&8tKwqs<+jV@0KIFX!mGv6fFpaj_~7P+SFCbj&st^Q#~3d+5a^7->no zqkH+zuVCy|yN%Z3aLeS@-oQ(&i+q;4!KpFn?B7o;(?Q+;JFjW!967E!?$vGLloam~$P&94E6}$Cu_)Y%Ws&G_t>CTBYgN0AV+& z6N&o4Y<>IWMfo836v&tHcEYD!BFWO&i^^|mr*Y9l_D-5wq!~iR21UoJcz~X{1%G_h zy8{_61zVUut!nhx^tYNF0(>0XgB@O>eTF-Vg<)nUD<^RP?-@ce7!hKEn}fXhLxwNC zN#c0O6^EH~-zs|#>uK;z>N5)sP4WmvJYINsph1eZKvUh?iMhfJ!tv_+#01y#Lp|d& i0xc$vN6>H4J+Sr@Z6b7ka`^g&TULgjfJp5(;6DIpKD?d) literal 0 HcmV?d00001 diff --git a/config/authelia/users_database.yml b/config/authelia/users_database.yml new file mode 100644 index 0000000..1c4b0eb --- /dev/null +++ b/config/authelia/users_database.yml @@ -0,0 +1,36 @@ +# yamllint disable rule:line-length +--- +############################################################### +# Users Database # +############################################################### + +# This file can be used if you do not have an LDAP set up. + + +users: + godopu16@godopu.net: + displayname: "Godopu" + password: "$argon2id$v=19$m=1024,t=1,p=8$YkdjeHNkdERqNzNTWHN1aw$ve9otTk53kLiBjCeWD5u9YJxU4EtoGKxNB7BTlEcRC4" # Password is 'Rhehvn16^^', salt is bGcxsdtDj73SXsuk + email: godopu16@godopu.net + groups: + - admins + - dev + + sjkoh: + displayname: "sjkoh" + password: "$argon2id$v=19$m=65536,t=3,p=4$VFx84S5QYd1J8WbI8NvdFw$BxFMZ/Vatqq8qdwtCTiR8qRLH8QgErMd9loNYgnBjSg" + email: sjkoh12@gmail.com + groups: + - admins + - dev + +... + + # supergint: + # displayname: "Dongle" + # password: "$argon2id$v=19$m=1024,t=1,p=8$c2NpM0RCcWM0UVVvSXNuaw$03SJ3Lk+WhvEzcJb7UpuuqKStqUw65pGuUj3cY9cVKg" # Password is 'Rhehvn16^^', salt is bGcxsdtDj73SXsuk + # email: supergint@gmail.com + # groups: + # - admins + # - dev +# yamllint enable rule:line-length diff --git a/config/traefik/router.yaml b/config/traefik/router.yaml new file mode 100644 index 0000000..40462d3 --- /dev/null +++ b/config/traefik/router.yaml @@ -0,0 +1,71 @@ +http: + routers: + to-traefik: + rule: Host(`traefik.godopu.net`) + service: traefik + entrypoints: http + middlewares: https-redirect + to-traefik-secure: + rule: Host(`traefik.godopu.net`) + service: traefik + entrypoints: https + tls: + certresolver: https-resolver + + to-iot-ws: + rule: Host(`iot.knu.ac.kr`) + service: iot-ws + entrypoints: http + middlewares: https-redirect + to-iot-ws-secure: + rule: Host(`iot.knu.ac.kr`) + service: iot-ws + entrypoints: https + tls: + certresolver: https-resolver + + to-protoecol-ws: + rule: Host(`protocol.knu.ac.kr`) + service: iot-ws + entrypoints: http + middlewares: https-redirect + to-protoecol-ws-secure: + rule: Host(`protocol.knu.ac.kr`) + service: iot-ws + entrypoints: https + tls: + certresolver: https-resolver + + to-authelia: + rule: Host(`auth.godopu.net`) + service: authelia + entrypoints: http + middlewares: https-redirect + to-authelia-secure: + rule: Host(`auth.godopu.net`) + service: authelia + entrypoints: https + tls: + certresolver: https-resolver + + middlewares: + https-redirect: + redirectscheme: + scheme: https + permanent: true + + services: + traefik: + loadBalancer: + servers: + - url: http://traefik:8080 + + iot-ws: + loadBalancer: + servers: + - url: http://iot-web-server:4000 + + authelia: + loadBalancer: + servers: + - url: http://authelia-app:9091 \ No newline at end of file diff --git a/config/traefik/traefik.yaml b/config/traefik/traefik.yaml new file mode 100644 index 0000000..4eb00ff --- /dev/null +++ b/config/traefik/traefik.yaml @@ -0,0 +1,65 @@ +experimental: + http3: true + +global: + checkNewVersion: true + sendAnonymousUsage: true + +certificatesResolvers: + https-resolver: + acme: + httpchallenge: + entrypoint: http + email: godopu16@gmail.com + storage: /letsencrypt/acme.json + +################################################################ +# Traefik logs configuration +################################################################ + +log: + level: DEBUG + +################################################################ +# Access logs configuration +################################################################ + +accessLog: + filePath: /traefik.log + bufferingSize: 100 + filters: + statusCodes: ["400-499"] + +################################################################ +# API and dashboard configuration +################################################################ + +api: + insecure: true + +################################################################ +# EntryPoints configuration +################################################################ + + +entryPoints: + http: + address: :80 + https: + address: :443 + +################################################################ +# Docker configuration backend +################################################################ +serversTransport: + insecureSkipVerify: true + +providers: + file: + directory: /etc/traefik/dynamic/conf + +# docker: +# exposedbydefault: false +# file: +# directory: /rules +# watch: true \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 8e5b384..994e76c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,29 +1,66 @@ version: '3' services: + traefik: + image: "docker.io/traefik:latest" + container_name: "traefik" + hostname: traefik + networks: + - lab-net + restart: always + expose: + - "80" + - "443" + - "8080" + command: + - "--configFile=/etc/traefik/dynamic/traefik.yaml" + ports: + - 80:80 + - 443:443 + - 8080:8080 + volumes: + - "./config/traefik/traefik.yaml:/etc/traefik/dynamic/traefik.yaml" + - "./config/traefik/router.yaml:/etc/traefik/dynamic/conf/router.yaml" + - "./volumes/traefik/letsencrypt:/letsencrypt" + - "./volumes/traefik/cert/:/certs/" + labels: + - "traefik.enable=true" + iot-web-server: + hostname: iot-web-server build: ./webserver image: iot-web-server/v0.1 networks: - lab-net - ports: - - 8080:8080 container_name: iot-web-server restart: always - hostname: iot-web-server volumes: - - "./iot-www:/home/www" + - "/home/sjkoh/www:/home/www" + openvscode-server: image: gitpod/openvscode-server:latest container_name: "openvscode-server" - ports: - - 3000:3000 + hostname: openvscode-server + networks: + - lab-net volumes: - - "./iot-www:/home/workspace" + - "/home/sjkoh/www:/home/workspace" entrypoint: - "/home/.openvscode-server/bin/openvscode-server" - "--host=0.0.0.0" - "--without-connection-token" # - "--connection-token=6b97db13-f2e3-41bb-a3a5-a18fdd1369e5" + authelia-app: + image: authelia/authelia:latest + container_name: authelia-app + hostname: authelia-app + networks: + - lab-net + restart: unless-stopped + ports: + - 9091:9091 + volumes: + - ./config/authelia:/config + networks: lab-net: null diff --git a/webserver/router/auth.go b/webserver/router/auth.go index 121083f..47feae7 100644 --- a/webserver/router/auth.go +++ b/webserver/router/auth.go @@ -17,7 +17,7 @@ import ( var ( // clientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID") // clientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET") - clientID = "godopu-dev" + clientID = "iot-ws" clientSecret = "mydwxdd-c2hbo6zcmab1mzj232zx4" ) var config oauth2.Config @@ -25,7 +25,7 @@ var provider *oidc.Provider func init() { var err error - provider, err = oidc.NewProvider(context.Background(), "https://auth.godopu.com") + provider, err = oidc.NewProvider(context.Background(), "https://auth.godopu.net") if err != nil { log.Fatal(err) } @@ -33,7 +33,7 @@ func init() { ClientID: clientID, ClientSecret: clientSecret, Endpoint: provider.Endpoint(), - RedirectURL: "http://localhost:4000/auth/oidc.callback", + RedirectURL: "https://iot.knu.ac.kr/auth/oidc.callback", Scopes: []string{oidc.ScopeOpenID, "profile", "email"}, } } @@ -97,14 +97,13 @@ func authCallback(ctx *gin.Context) { c := &http.Cookie{ Name: "__edit_access_token_", - Value: "value", + Value: "temporary-token", MaxAge: int(time.Hour.Seconds()), Secure: ctx.Request.TLS != nil, HttpOnly: true, Path: "/", } - ctx.Set("__edit_access_token_", "^^") http.SetCookie(ctx.Writer, c) ctx.Redirect(http.StatusFound, "/edit") } diff --git a/webserver/router/reverse_proxy.go b/webserver/router/reverse_proxy.go index d5f0464..c4f8cc7 100644 --- a/webserver/router/reverse_proxy.go +++ b/webserver/router/reverse_proxy.go @@ -13,7 +13,7 @@ func reverseProxyHandle(c *gin.Context) { path := c.Param("any") - remote, err := url.Parse("http://localhost:3000") + remote, err := url.Parse("http://openvscode-server:3000") if err != nil { panic(err) } diff --git a/webserver/router/route.go b/webserver/router/route.go index 1383ac7..8cf34c9 100644 --- a/webserver/router/route.go +++ b/webserver/router/route.go @@ -11,7 +11,7 @@ import ( func NewRouter() *gin.Engine { assetEngine := gin.New() - assetEngine.Static("/home", "../iot-www") + assetEngine.Static("/home", "./www") r := gin.New()