Make use of CORS, add more tests
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
87c77f6966
commit
535f39a1ba
9 changed files with 310 additions and 5 deletions
|
|
@ -32,6 +32,8 @@ import (
|
|||
"garm/runner"
|
||||
"garm/util"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
|
@ -117,6 +119,12 @@ func main() {
|
|||
}
|
||||
|
||||
router := routers.NewAPIRouter(controller, logWriter, jwtMiddleware, initMiddleware, instanceMiddleware)
|
||||
corsMw := mux.CORSMethodMiddleware(router)
|
||||
router.Use(corsMw)
|
||||
|
||||
allowedOrigins := handlers.AllowedOrigins(cfg.APIServer.CORSOrigins)
|
||||
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE"})
|
||||
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"})
|
||||
|
||||
tlsCfg, err := cfg.APIServer.APITLSConfig()
|
||||
if err != nil {
|
||||
|
|
@ -127,7 +135,7 @@ func main() {
|
|||
Addr: cfg.APIServer.BindAddress(),
|
||||
TLSConfig: tlsCfg,
|
||||
// Pass our instance of gorilla/mux in.
|
||||
Handler: router,
|
||||
Handler: handlers.CORS(methodsOk, headersOk, allowedOrigins)(router),
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", srv.Addr)
|
||||
|
|
|
|||
|
|
@ -141,10 +141,19 @@ func (c *Config) Validate() error {
|
|||
return errors.Wrap(err, "validating jwt config")
|
||||
}
|
||||
|
||||
providerNames := map[string]int{}
|
||||
|
||||
for _, provider := range c.Providers {
|
||||
if err := provider.Validate(); err != nil {
|
||||
return errors.Wrap(err, "validating provider")
|
||||
}
|
||||
providerNames[provider.Name] += 1
|
||||
}
|
||||
|
||||
for name, count := range providerNames {
|
||||
if count > 1 {
|
||||
return fmt.Errorf("duplicate provider name %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -165,10 +174,12 @@ func (d *Default) Validate() error {
|
|||
return fmt.Errorf("missing callback_url")
|
||||
}
|
||||
|
||||
if d.ConfigDir != "" {
|
||||
if _, err := os.Stat(d.ConfigDir); err != nil {
|
||||
return errors.Wrap(err, "accessing config dir")
|
||||
}
|
||||
if d.ConfigDir == "" {
|
||||
return fmt.Errorf("config_dir cannot be empty")
|
||||
}
|
||||
|
||||
if _, err := os.Stat(d.ConfigDir); err != nil {
|
||||
return errors.Wrap(err, "accessing config dir")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1 +1,175 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var (
|
||||
EncryptionPassphrase = "bocyasicgatEtenOubwonIbsudNutDom"
|
||||
)
|
||||
|
||||
func getDefaultSectionConfig(configDir string) Default {
|
||||
return Default{
|
||||
ConfigDir: configDir,
|
||||
CallbackURL: "https://garm.example.com/",
|
||||
LogFile: filepath.Join(configDir, "garm.log"),
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultTLSConfig() TLSConfig {
|
||||
return TLSConfig{
|
||||
CRT: "../testdata/certs/srv-pub.pem",
|
||||
Key: "../testdata/certs/srv-key.pem",
|
||||
CACert: "../testdata/certs/ca-pub.pem",
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultAPIServerConfig() APIServer {
|
||||
return APIServer{
|
||||
Bind: "0.0.0.0",
|
||||
Port: 9998,
|
||||
UseTLS: true,
|
||||
TLSConfig: getDefaultTLSConfig(),
|
||||
CORSOrigins: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultDatabaseConfig(dir string) Database {
|
||||
return Database{
|
||||
Debug: false,
|
||||
DbBackend: SQLiteBackend,
|
||||
SQLite: SQLite{
|
||||
DBFile: filepath.Join(dir, "garm.db"),
|
||||
},
|
||||
Passphrase: EncryptionPassphrase,
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultProvidersConfig() []Provider {
|
||||
lxdConfig := getDefaultLXDConfig()
|
||||
return []Provider{
|
||||
{
|
||||
Name: "test_lxd",
|
||||
ProviderType: LXDProvider,
|
||||
Description: "test LXD provider",
|
||||
LXD: lxdConfig,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultGithubConfig() []Github {
|
||||
return []Github{
|
||||
{
|
||||
Name: "dummy_creds",
|
||||
Description: "dummy github credentials",
|
||||
OAuth2Token: "bogus",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultJWTCofig() JWTAuth {
|
||||
return JWTAuth{
|
||||
Secret: EncryptionPassphrase,
|
||||
TimeToLive: "48h",
|
||||
}
|
||||
}
|
||||
|
||||
func getDefaultConfig(t *testing.T) Config {
|
||||
dir, err := ioutil.TempDir("", "garm-config-test")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temporary directory: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { os.RemoveAll(dir) })
|
||||
|
||||
return Config{
|
||||
Default: getDefaultSectionConfig(dir),
|
||||
APIServer: getDefaultAPIServerConfig(),
|
||||
Database: getDefaultDatabaseConfig(dir),
|
||||
Providers: getDefaultProvidersConfig(),
|
||||
Github: getDefaultGithubConfig(),
|
||||
JWTAuth: getDefaultJWTCofig(),
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
cfg := getDefaultConfig(t)
|
||||
|
||||
err := cfg.Validate()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestDefaultSectionConfig(t *testing.T) {
|
||||
dir, err := ioutil.TempDir("", "garm-config-test")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create temporary directory: %s", err)
|
||||
}
|
||||
t.Cleanup(func() { os.RemoveAll(dir) })
|
||||
cfg := getDefaultSectionConfig(dir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg Default
|
||||
errString string
|
||||
}{
|
||||
{
|
||||
name: "Config is valid",
|
||||
cfg: cfg,
|
||||
errString: "",
|
||||
},
|
||||
{
|
||||
name: "CallbackURL cannot be empty",
|
||||
cfg: Default{
|
||||
CallbackURL: "",
|
||||
ConfigDir: cfg.ConfigDir,
|
||||
},
|
||||
errString: "missing callback_url",
|
||||
},
|
||||
{
|
||||
name: "ConfigDir cannot be empty",
|
||||
cfg: Default{
|
||||
CallbackURL: cfg.CallbackURL,
|
||||
ConfigDir: "",
|
||||
},
|
||||
errString: "config_dir cannot be empty",
|
||||
},
|
||||
{
|
||||
name: "config_dir must exist and be accessible",
|
||||
cfg: Default{
|
||||
CallbackURL: cfg.CallbackURL,
|
||||
ConfigDir: "/i/do/not/exist",
|
||||
},
|
||||
errString: "accessing config dir: stat /i/do/not/exist:.*",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := tc.cfg.Validate()
|
||||
if tc.errString == "" {
|
||||
assert.Nil(t, err)
|
||||
} else {
|
||||
assert.NotNil(t, err)
|
||||
assert.Regexp(t, tc.errString, err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
|
|
|
|||
20
testdata/certs/ca-pub.pem
vendored
Normal file
20
testdata/certs/ca-pub.pem
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDTDCCAjSgAwIBAgIRAMrfG/ZCst3T0RtRgcnY5h0wDQYJKoZIhvcNAQELBQAw
|
||||
MDEcMBoGA1UEChMTQ2xvdWRiYXNlIFNvbHV0aW9uczEQMA4GA1UEAxMHUm9vdCBD
|
||||
QTAeFw0yMjA3MDQxODM3MjdaFw0zMjA3MDExODM3MjdaMDAxHDAaBgNVBAoTE0Ns
|
||||
b3VkYmFzZSBTb2x1dGlvbnMxEDAOBgNVBAMTB1Jvb3QgQ0EwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQCooxNCaSfs8UhVmavARonC5S2mFLCSLXrHGPhS
|
||||
+hjAgqQrF8pI/LvJmsV1LAjYjIAqwE9eDIbuyj8nBuaPJYFoS4McaKZmuo/UYqgx
|
||||
5K+rDfMdDUFIP0XGTopJFcfKguQQU6Tx+8v5Ubc8C9WjRFDRbmR5ihNzKb1Eb/y1
|
||||
OrwmsNtMmgyZFCm6yDMymXFgqTo58zTj9d04uwumVLjSoJxPEqytf9LpKJoeoj7O
|
||||
tnSq8OMPyhsPu3LgZyvyB65ehb1NChica99Dh5bee4muQAkYGUqbRXgbau6edhsQ
|
||||
MtXM4mzaXdQIMva3rPfnBfPuhc9WjnKmmmOsWDv510nbl0hVAgMBAAGjYTBfMA4G
|
||||
A1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDwYD
|
||||
VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoesgOFlL4kKwT1enjyGkxCEUPSowDQYJ
|
||||
KoZIhvcNAQELBQADggEBAHlWX8iDkTtADKMAbfBMzvsolzQjZALMab2Jdco7QKtO
|
||||
i3g6k7UWsgAO+cbH8XCM87ty6JuPUFJNibLWHl1A4dSqwbGGNw+wLVLqNzu8dDqC
|
||||
E1WG3rIFkXFa3z3eZhauBcdp2FCLbuHtD4g/yGHE/LExnIZeHMpbF2MuC0V34PhY
|
||||
daj2FUYJe+hmiKRajXGYjv6jOTAbylLK8qzF7HmTnLIJ0hahmKnykC2FiwAVpxZC
|
||||
T0OcNEXjR1FJfSVHJC2OCOZXPftP7ssZmO18j35UMGk/oxkrUz0839rQtT5oZPI6
|
||||
UuNSyP3+BcQtdrDUiCOum651ojwvEO4umlQX3zGmo7U=
|
||||
-----END CERTIFICATE-----
|
||||
27
testdata/certs/srv-key.pem
vendored
Normal file
27
testdata/certs/srv-key.pem
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAyUksz2y+noPUEebojEhMmMUWV9Co+wEWx7QUnWuT9ywaU+Jl
|
||||
4hucM8W+2kgLz4eo0Ih9TOgMasSeCXFQCYdHA6AHzUmzO54i3kuliRFP5QXnOoPS
|
||||
Z5t8GrcnuX3eZ/VAlgdMygs74R1fBn3vCNIY9PVdoaR7dd66Nx1U13ayHG3Z9LnM
|
||||
FMa0T2snnjONv3iL2ctZIlOKbYgOvKa9yjyGdSne20RJG659dpF8/0ovz6BmaRVl
|
||||
5sE1sfF9Y84WXkZjDAvfg8rtTXSwSsuZeRlPz+wEP3tKtzCjzcUr61bd7M456pwD
|
||||
9Y19dRsGEqP4A5tZ/xTeHol604n9STcKdxfVfwIDAQABAoIBAQC+SACmbcSdkT3v
|
||||
VnxL8SUH3njKtySndFYWn7RFRKdyKC0TU5jA8RzvDGbpbuZLX5FE4WKiS1NBs3E6
|
||||
t/XTrCCD2srFVICtQUbxIk3wj38ZoEUA2hEThLcDglV5UvXnDL/rlCcRcSFAJEXq
|
||||
my5XBlY1a6cB4b4cpVsgMwg7T6f8mmcQv7Y5CjIH3P8RSjAQpoDRPCcDnEWieDnV
|
||||
NDTPFKvOdXe01XMJ7YJ9jd3RE4exra3xeDJgB0EPxexlDpcLMxDEt3JfEbzr3xdc
|
||||
sSXQbVzriYRv8jYV0xAond6itVDfoH6qGVGP+YiSKLeHbcML8WjeFtUhG8gYl/OX
|
||||
RkrHzVGRAoGBAOYbyN6cb7EWDyr6V+s8o/lD67Zs1SCoa7mMxjbTsjuGuEjNsoLU
|
||||
CetAUCbay7NZl37fwm7QE5PbOjr1ED6tgSi3Za9M/3GITFIrqRVbfIP5nyfJgbUQ
|
||||
QLBZ9sb22rrWz5IWFx0jxWQzO6g3ZEPgRt47OO9xBmfJr77A+FRzNnEFAoGBAN/v
|
||||
KQu2xBIdq4aiai/EepHG0YLToMVCgx0CZiajdl9QhJW4oBBYnYDm/elZSdksDmjy
|
||||
8J80yUeZBQIkL6o2qIBrkrrcPl019KUtljiTDNQQhQqRqmN/HZxZXFXDVoMLvdJf
|
||||
LQejtmT93pD4SsrQ8T5fV8qDjybSSKtw5A1zMMOzAoGAJZN389I78wEVLQGAhet7
|
||||
I2NSBJI1I4YdQUmZvK5JNqtDQLBGbFLP49i2vgGQrhL9SDyl9Y6JA+YS1jnak0Gm
|
||||
C84XDs9WD2YggHKcw94SsUJ8GPUw9y5WQfYO9GKvST922fY9hAapXzl2jnutJeBj
|
||||
8jpdi8w7LYuj5VSBuNivlTkCgYAibAbpMAzvo/Pr3CdqdE9K/T7TV2iNKe4xlV7S
|
||||
baoSeLQIt7qTCKwdVmSNbBY39de5Ni7aqiiOgu0MKTfSeFhqdR627of/l/2lLl67
|
||||
D4+XQXrR5xZD+RQ6JlpVLJOtzS4+mja3x+iPmZ6Otjv49SlAJzO9g3+LviNBhzbn
|
||||
Al/qlQKBgQCOx15o+udsT2LlVOUL6Gt6TBoin6BmepGK4plFPVs83pM2Ce7oYhr/
|
||||
MBpgYO/CiYzFkWJdY91IHRswt8MYqIxpBZNv1TZntHlHVItEzgidSU8BkxMte8u4
|
||||
iAvNm8KCSwFVopwcXaGOxtqUAgX7rJo9+y22KBMtYBAq1RWDI5DlOg==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
23
testdata/certs/srv-pub.pem
vendored
Normal file
23
testdata/certs/srv-pub.pem
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIID1DCCArygAwIBAgIRAMlzfk77HwnF4vq4FSp5cvEwDQYJKoZIhvcNAQELBQAw
|
||||
MDEcMBoGA1UEChMTQ2xvdWRiYXNlIFNvbHV0aW9uczEQMA4GA1UEAxMHUm9vdCBD
|
||||
QTAeFw0yMjA3MDQxODM3MjdaFw0zMjA3MDExODM3MjdaMDMxHDAaBgNVBAoTE0Ns
|
||||
b3VkYmFzZSBTb2x1dGlvbnMxEzARBgNVBAMTCnJlcGxpY2F0b3IwggEiMA0GCSqG
|
||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJSSzPbL6eg9QR5uiMSEyYxRZX0Kj7ARbH
|
||||
tBSda5P3LBpT4mXiG5wzxb7aSAvPh6jQiH1M6AxqxJ4JcVAJh0cDoAfNSbM7niLe
|
||||
S6WJEU/lBec6g9Jnm3watye5fd5n9UCWB0zKCzvhHV8Gfe8I0hj09V2hpHt13ro3
|
||||
HVTXdrIcbdn0ucwUxrRPayeeM42/eIvZy1kiU4ptiA68pr3KPIZ1Kd7bREkbrn12
|
||||
kXz/Si/PoGZpFWXmwTWx8X1jzhZeRmMMC9+Dyu1NdLBKy5l5GU/P7AQ/e0q3MKPN
|
||||
xSvrVt3szjnqnAP1jX11GwYSo/gDm1n/FN4eiXrTif1JNwp3F9V/AgMBAAGjgeUw
|
||||
geIwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB
|
||||
/wQCMAAwgawGA1UdEQSBpDCBoYIEZ2FybYIKZ2FybS5sb2NhbIIJbG9jYWxob3N0
|
||||
hwQKxnUxhxAqAQT5AEsXXoAAAAAAAAAEhxD+gAAAAAAAAAIWPv/+yxHIhwQK9/YB
|
||||
hxD+gAAAAAAAAAIWPv/+WxRvhwRkeIJUhxD9ehFcoeCrEkhDzZZieIJUhxD+gAAA
|
||||
AAAAAGBnFVzKxAsbhwSsEQABhxD+gAAAAAAAAABCKP/+U3+HMA0GCSqGSIb3DQEB
|
||||
CwUAA4IBAQBxo48eWMMSYBcPvON8fVURTw58OSuW4iw7GTOCZIluQybXfhg7b/CC
|
||||
BOHwrW6F+j3iIpgQx5AVofGldGKRcCdqg+uToP6rZQvHkoIGwbkTvFLxSnhrr0rc
|
||||
4fvkgloVEV2Oyf7lFDES64MKh8U+baXgwyUl++vrwSmTv2BCCAG5XNFN8jvAEHLu
|
||||
wCB6NY6X2RriUGoBr1dIJeDWjYMLQqBh2m9+8vCLsQ7A7TzDJfF7JxhHV94qZ4c4
|
||||
LKaBdKxl4UGr6HuRMPapsoQqVWV+ZjZrPf4LSoj3DenNwzOc/Rm3Nya8xDCCLxqu
|
||||
RgNpSos4SD2WTF1RG2buzmgrsdvd3mWX
|
||||
-----END CERTIFICATE-----
|
||||
Loading…
Add table
Add a link
Reference in a new issue