From 91c0ed863a7d514b65db79ae4eb85822f0f0f508 Mon Sep 17 00:00:00 2001 From: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com> Date: Wed, 8 Jun 2022 19:28:28 +0100 Subject: [PATCH] [bugfix] #621: add weak type handing to mapstructure decode (#625) * Drone sig (#623) * accept weakly typed input on mapstructure decode i.e. .UnmarshalMap() Signed-off-by: kim * add envparsing script to test for panics during environment variable parsing Signed-off-by: kim * add envparsing.sh script to drone commands Signed-off-by: kim * update drone signature Co-authored-by: kim * compare expected with output * update expected output of envparsing * update expected output to correct value * use viper's unmarshal function instead There were problems with marshalling string slices from viper into the st.config struct with the other function. Now, we can use viper's unmarshal function and pass in the custom decoder config that we need as a hook. This ensures that we marshal string slices from viper into our config struct correctly. Co-authored-by: tobi <31960611+tsmethurst@users.noreply.github.com> Co-authored-by: tsmethurst --- .drone.yml | 3 +- internal/config/config.go | 9 ----- internal/config/state.go | 7 ++-- test/envparsing.sh | 70 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 12 deletions(-) create mode 100755 test/envparsing.sh diff --git a/.drone.yml b/.drone.yml index a96d54649..bec186175 100644 --- a/.drone.yml +++ b/.drone.yml @@ -38,6 +38,7 @@ steps: - apk update --no-cache && apk add git - CGO_ENABLED=0 GTS_DB_TYPE="sqlite" GTS_DB_ADDRESS=":memory:" go test ./... - CGO_ENABLED=0 ./test/cliparsing.sh + - CGO_ENABLED=0 ./test/envparsing.sh when: event: include: @@ -145,6 +146,6 @@ steps: --- kind: signature -hmac: f3cf4e422d9ce7dc0a881da429db628232e2f9e91383ee5a33cf4f13542c0a23 +hmac: adfcc11559717e4e371e714f3ac19ab528208f678961436f316f491bf82de8ad ... diff --git a/internal/config/config.go b/internal/config/config.go index 573f2b3a2..3a1775778 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -130,12 +130,3 @@ func (cfg *Configuration) MarshalMap() (map[string]interface{}, error) { } return dst, nil } - -// UnmarshalMap will unmarshal a map structure into the receiving Configuration. -func (cfg *Configuration) UnmarshalMap(src map[string]interface{}) error { - dec, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ - TagName: "name", - Result: cfg, - }) - return dec.Decode(src) -} diff --git a/internal/config/state.go b/internal/config/state.go index 70972a835..1364fb84e 100644 --- a/internal/config/state.go +++ b/internal/config/state.go @@ -22,6 +22,7 @@ import ( "strings" "sync" + "github.com/mitchellh/mapstructure" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -129,8 +130,10 @@ func (st *ConfigState) reloadToViper() { // reloadFromViper will reload Configuration{} values from viper. func (st *ConfigState) reloadFromViper() { - err := st.config.UnmarshalMap(st.viper.AllSettings()) - if err != nil { + if err := st.viper.Unmarshal(&st.config, func(c *mapstructure.DecoderConfig) { + c.TagName = "name" + c.ZeroFields = true // empty the config struct before we marshal values into it + }); err != nil { panic(err) } } diff --git a/test/envparsing.sh b/test/envparsing.sh new file mode 100755 index 000000000..8bced72e9 --- /dev/null +++ b/test/envparsing.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +set -eu + +EXPECTED='{"account-domain":"peepee","accounts-approval-required":false,"accounts-reason-required":false,"accounts-registration-open":true,"advanced-cookies-samesite":"strict","application-name":"gts","bind-address":"127.0.0.1","config-path":"./test/test.yaml","db-address":":memory:","db-database":"gotosocial_prod","db-password":"hunter2","db-port":6969,"db-tls-ca-cert":"","db-tls-mode":"disable","db-type":"sqlite","db-user":"sex-haver","email":"","host":"example.com","letsencrypt-cert-dir":"/gotosocial/storage/certs","letsencrypt-email-address":"","letsencrypt-enabled":true,"letsencrypt-port":80,"log-db-queries":true,"log-level":"info","media-description-max-chars":5000,"media-description-min-chars":69,"media-image-max-size":420,"media-remote-cache-days":30,"media-video-max-size":420,"oidc-client-id":"1234","oidc-client-secret":"shhhh its a secret","oidc-enabled":true,"oidc-idp-name":"sex-haver","oidc-issuer":"whoknows","oidc-scopes":["read","write"],"oidc-skip-verification":true,"password":"","path":"","port":6969,"protocol":"http","smtp-from":"queen@terfisland.org","smtp-host":"example.com","smtp-password":"hunter2","smtp-port":4269,"smtp-username":"sex-haver","software-version":"","statuses-cw-max-chars":420,"statuses-max-chars":69,"statuses-media-max-files":1,"statuses-poll-max-options":1,"statuses-poll-option-max-chars":50,"storage-backend":"local","storage-local-base-path":"/root/store","syslog-address":"127.0.0.1:6969","syslog-enabled":true,"syslog-protocol":"udp","trusted-proxies":["127.0.0.1/32","0.0.0.0/0"],"username":"","web-asset-base-dir":"/root","web-template-base-dir":"/root"}' + +# Set all the environment variables to +# ensure that these are parsed without panic +OUTPUT=$(GTS_LOG_LEVEL='info' \ +GTS_LOG_DB_QUERIES=true \ +GTS_APPLICATION_NAME=gts \ +GTS_HOST=example.com \ +GTS_ACCOUNT_DOMAIN='peepee' \ +GTS_PROTOCOL=http \ +GTS_BIND_ADDRESS='127.0.0.1' \ +GTS_PORT=6969 \ +GTS_TRUSTED_PROXIES='' \ +GTS_DB_TYPE='sqlite' \ +GTS_DB_ADDRESS=':memory:' \ +GTS_DB_PORT=6969 \ +GTS_DB_USER='sex-haver' \ +GTS_DB_PASSWORD='hunter2' \ +GTS_DB_DATABASE='gotosocial_prod' \ +GTS_TLS_MODE='' \ +GTS_DB_TLS_CA_CERT='' \ +GTS_WEB_TEMPLATE_BASE_DIR='/root' \ +GTS_WEB_ASSET_BASE_DIR='/root' \ +GTS_ACCOUNTS_REGISTRATION_OPEN=true \ +GTS_ACCOUNTS_APPROVAL_REQUIRED=false \ +GTS_ACCOUNTS_REASON_REQUIRED=false \ +GTS_MEDIA_IMAGE_MAX_SIZE=420 \ +GTS_MEDIA_VIDEO_MAX_SIZE=420 \ +GTS_MEDIA_DESCRIPTION_MIN_CHARS=69 \ +GTS_MEDIA_DESCRIPTION_MAX_CHARS=5000 \ +GTS_MEDIA_REMOTE_CACHE_DAYS=30 \ +GTS_STORAGE_BACKEND='local' \ +GTS_STORAGE_LOCAL_BASE_PATH='/root/store' \ +GTS_STATUSES_MAX_CHARS=69 \ +GTS_STATUSES_CW_MAX_CHARS=420 \ +GTS_STATUSES_POLL_MAX_OPTIONS=1 \ +GTS_STATUSES_POLL_OPTIONS_MAX_CHARS=69 \ +GTS_STATUSES_MEDIA_MAX_FILES=1 \ +GTS_LETS_ENCRYPT_ENABLED=false \ +GTS_LETS_ENCRYPT_PORT=8080 \ +GTS_LETS_ENCRYPT_CERT_DIR='/root/certs' \ +GTS_LETS_ENCRYPT_EMAIL_ADDRESS='le@example.com' \ +GTS_OIDC_ENABLED=true \ +GTS_OIDC_IDP_NAME='sex-haver' \ +GTS_OIDC_SKIP_VERIFICATION=true \ +GTS_OIDC_ISSUER='whoknows' \ +GTS_OIDC_CLIENT_ID='1234' \ +GTS_OIDC_CLIENT_SECRET='shhhh its a secret' \ +GTS_OIDC_SCOPES='read,write' \ +GTS_SMTP_HOST='example.com' \ +GTS_SMTP_PORT=4269 \ +GTS_SMTP_USERNAME='sex-haver' \ +GTS_SMTP_PASSWORD='hunter2' \ +GTS_SMTP_FROM='queen@terfisland.org' \ +GTS_SYSLOG_ENABLED=true \ +GTS_SYSLOG_PROTOCOL='udp' \ +GTS_SYSLOG_ADDRESS='127.0.0.1:6969' \ +GTS_ADVANCED_COOKIES_SAMESITE='strict' \ +go run ./cmd/gotosocial/... --config-path $(dirname ${0})/test.yaml debug config) + +if [ "${OUTPUT}" != "${EXPECTED}" ]; then + echo "OUTPUT not equal EXPECTED" + exit 1 +else + echo "OK" +fi