Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support XDG config path #951

Merged
merged 1 commit into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
* Replace `--port` with `--server` flag for the `aws-sso ecs [list|load|unload|profile]` commands #937
* Update cache during login when relevant settings in the config.yaml changes #555
* Add support for `$AWS_SHARED_CREDENTIALS_FILE` #914
* Add support for `~/.config/aws-sso` #330

### Changes

* Bump cache file version to 4.
* `ConfigProfilesUrlAction` now defaults to value of `UrlAction` instead of `url` #946
* Rename/rework many of the `ecs` commands #938
* New installs of `aws-sso` will default to `~/.config/aws-sso` instead of `~/.aws-sso` for configuration

## [v1.16.1] - 2024-06-13

Expand Down
23 changes: 10 additions & 13 deletions cmd/aws-sso/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
// "github.com/davecgh/go-spew/spew"
"github.com/sirupsen/logrus"
"github.com/synfinatic/aws-sso-cli/internal/awscreds"
"github.com/synfinatic/aws-sso-cli/internal/config"
"github.com/synfinatic/aws-sso-cli/internal/ecs"
"github.com/synfinatic/aws-sso-cli/internal/ecs/client"
"github.com/synfinatic/aws-sso-cli/internal/ecs/server"
Expand Down Expand Up @@ -60,12 +61,8 @@ type RunContext struct {
}

const (
CONFIG_DIR = "~/.aws-sso"
CONFIG_FILE = CONFIG_DIR + "/config.yaml"
JSON_STORE_FILE = CONFIG_DIR + "/store.json"
INSECURE_CACHE_FILE = CONFIG_DIR + "/cache.json"
DEFAULT_STORE = "file"
COPYRIGHT_YEAR = "2021-2024"
DEFAULT_STORE = "file"
COPYRIGHT_YEAR = "2021-2024"
)

var DEFAULT_CONFIG map[string]interface{} = map[string]interface{}{
Expand Down Expand Up @@ -192,7 +189,7 @@ func main() {
log.WithError(err).Fatalf("Unable to open config file: %s", cli.ConfigFile)
}

cacheFile := utils.GetHomePath(INSECURE_CACHE_FILE)
cacheFile := config.InsecureCacheFile(true)

if runCtx.Settings, err = sso.LoadSettings(cli.ConfigFile, cacheFile, DEFAULT_CONFIG, override); err != nil {
log.Fatalf("%s", err.Error())
Expand All @@ -201,7 +198,7 @@ func main() {
// Load the secure store data
switch runCtx.Settings.SecureStore {
case "json":
sfile := utils.GetHomePath(JSON_STORE_FILE)
sfile := config.JsonStoreFile(true)
if runCtx.Settings.JsonStore != "" {
sfile = utils.GetHomePath(runCtx.Settings.JsonStore)
}
Expand All @@ -211,7 +208,7 @@ func main() {
}
log.Warnf("Using insecure json file for SecureStore: %s", sfile)
default:
cfg, err := storage.NewKeyringConfig(runCtx.Settings.SecureStore, CONFIG_DIR)
cfg, err := storage.NewKeyringConfig(runCtx.Settings.SecureStore, config.ConfigDir(true))
if err != nil {
log.WithError(err).Fatalf("Unable to create SecureStore")
}
Expand All @@ -231,10 +228,10 @@ func main() {
func parseArgs(cli *CLI) (*kong.Context, sso.OverrideSettings) {
// need to pass in the variables for defaults
vars := kong.Vars{
"CONFIG_DIR": CONFIG_DIR,
"CONFIG_FILE": CONFIG_FILE,
"CONFIG_DIR": config.ConfigDir(false),
"CONFIG_FILE": config.ConfigFile(false),
"DEFAULT_STORE": DEFAULT_STORE,
"JSON_STORE_FILE": JSON_STORE_FILE,
"JSON_STORE_FILE": config.JsonStoreFile(false),
"VERSION": Version,
}

Expand All @@ -245,7 +242,7 @@ func parseArgs(cli *CLI) (*kong.Context, sso.OverrideSettings) {
vars,
)

p := predictor.NewPredictor(utils.GetHomePath(INSECURE_CACHE_FILE), utils.GetHomePath(CONFIG_FILE))
p := predictor.NewPredictor(config.InsecureCacheFile(true), config.ConfigFile(true))

kongplete.Complete(parser,
kongplete.WithPredictors(
Expand Down
15 changes: 12 additions & 3 deletions docs/config.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
# Configuration

By default, `aws-sso` stores it's configuration file in `~/.aws-sso/config.yaml`,
but this can be overridden by setting `$AWS_SSO_CONFIG` in your shell or via the
`--config` flag.
By default, `aws-sso` will by default store all it's configuration and state files in
`~/.config/aws-sso` for versions `>= 1.17.0` per the [XDG spec](
https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).
Previous versions of `aws-sso` used `~/.aws-sso`. Users at their own descresion may move the
files to the new location. To keep files co-located in the same place, if the directory
`~/.aws-sso` exists, then it will be used.

**Note:** The `aws-sso` documentation will generally use the older file path (`~/.aws-sso/...`)
when describing file locations.

The main configuration file is named `~/.aws-sso/config.yaml`, but this can be overridden by
setting `$AWS_SSO_CONFIG` in your shell or via the `--config` flag.

The first time you run `aws-sso` and it detects there is no configuration file,
it will prompt you for a number of questions to give you a basic configuration.
Expand Down
94 changes: 94 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package config

/*
* AWS SSO CLI
* Copyright (c) 2021-2024 Aaron Turner <synfinatic at gmail dot com>
*
* This program is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or with the authors permission any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import (
"fmt"
"os"

"github.com/synfinatic/aws-sso-cli/internal/utils"
)

const (
OLD_CONFIG_DIR = "~/.aws-sso"
CONFIG_DIR = "~/.config/aws-sso"
CONFIG_FILE = "%s/config.yaml"
JSON_STORE_FILE = "%s/store.json"
INSECURE_CACHE_FILE = "%s/cache.json"
)

func ConfigDir(expand bool) string {
var path string
fi, err := os.Stat(utils.GetHomePath(OLD_CONFIG_DIR))
if err == nil && fi.IsDir() {
path = OLD_CONFIG_DIR
} else {
path = CONFIG_DIR
}
if expand {
path = utils.GetHomePath(path)
}
return path
}

// ConfigFile returns the path to the config file
func ConfigFile(expand bool) string {
var path string
fi, err := os.Stat(utils.GetHomePath(OLD_CONFIG_DIR))
fmt.Printf("fi: %v, err: %v\n", fi, err)
if err == nil && fi.IsDir() {
path = fmt.Sprintf(CONFIG_FILE, OLD_CONFIG_DIR)
} else {
path = fmt.Sprintf(CONFIG_FILE, CONFIG_DIR)
}
if expand {
path = utils.GetHomePath(path)
}
return path
}

// JsonStoreFile returns the path to the JSON store file
func JsonStoreFile(expand bool) string {
var path string
fi, err := os.Stat(utils.GetHomePath(OLD_CONFIG_DIR))
if err == nil && fi.IsDir() {
path = fmt.Sprintf(JSON_STORE_FILE, OLD_CONFIG_DIR)
} else {
path = fmt.Sprintf(JSON_STORE_FILE, CONFIG_DIR)
}
if expand {
path = utils.GetHomePath(path)
}
return path
}

// InsecureCacheFile returns the path to the insecure cache file
func InsecureCacheFile(expand bool) string {
var path string
fi, err := os.Stat(utils.GetHomePath(OLD_CONFIG_DIR))
if err == nil && fi.IsDir() {
path = fmt.Sprintf(INSECURE_CACHE_FILE, OLD_CONFIG_DIR)
} else {
path = fmt.Sprintf(INSECURE_CACHE_FILE, CONFIG_DIR)
}
if expand {
path = utils.GetHomePath(path)
}
return path
}
72 changes: 72 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package config

import (
"fmt"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestConfigDir(t *testing.T) {
home := os.Getenv("HOME")
tempDir, err := os.MkdirTemp("", "")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)

os.Setenv("HOME", tempDir)
defer os.Setenv("HOME", home)

assert.Equal(t, tempDir+"/.config/aws-sso", ConfigDir(true))
assert.Equal(t, "~/.config/aws-sso", ConfigDir(false))
_ = os.MkdirAll(fmt.Sprintf("%s/.aws-sso", tempDir), 0755)
assert.Equal(t, tempDir+"/.aws-sso", ConfigDir(true))
assert.Equal(t, "~/.aws-sso", ConfigDir(false))
}
func TestConfigFile(t *testing.T) {
tempDir, err := os.MkdirTemp("", "")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)

os.Setenv("HOME", tempDir)
home := os.Getenv("HOME")
defer os.Setenv("HOME", home)

assert.Equal(t, tempDir+"/.config/aws-sso/config.yaml", ConfigFile(true))
assert.Equal(t, "~/.config/aws-sso/config.yaml", ConfigFile(false))
_ = os.MkdirAll(fmt.Sprintf("%s/.aws-sso", tempDir), 0755)
assert.Equal(t, tempDir+"/.aws-sso/config.yaml", ConfigFile(true))
assert.Equal(t, "~/.aws-sso/config.yaml", ConfigFile(false))
}

func TestJsonStoreFile(t *testing.T) {
tempDir, err := os.MkdirTemp("", "")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)

os.Setenv("HOME", tempDir)
home := os.Getenv("HOME")
defer os.Setenv("HOME", home)

assert.Equal(t, tempDir+"/.config/aws-sso/store.json", JsonStoreFile(true))
assert.Equal(t, "~/.config/aws-sso/store.json", JsonStoreFile(false))
_ = os.MkdirAll(fmt.Sprintf("%s/.aws-sso", tempDir), 0755)
assert.Equal(t, tempDir+"/.aws-sso/store.json", JsonStoreFile(true))
assert.Equal(t, "~/.aws-sso/store.json", JsonStoreFile(false))
}

func TestInsecureCacheFile(t *testing.T) {
tempDir, err := os.MkdirTemp("", "")
assert.NoError(t, err)
defer os.RemoveAll(tempDir)

os.Setenv("HOME", tempDir)
home := os.Getenv("HOME")
defer os.Setenv("HOME", home)

assert.Equal(t, tempDir+"/.config/aws-sso/cache.json", InsecureCacheFile(true))
assert.Equal(t, "~/.config/aws-sso/cache.json", InsecureCacheFile(false))
_ = os.MkdirAll(fmt.Sprintf("%s/.aws-sso", tempDir), 0755)
assert.Equal(t, tempDir+"/.aws-sso/cache.json", InsecureCacheFile(true))
assert.Equal(t, "~/.aws-sso/cache.json", InsecureCacheFile(false))
}
Loading