Configuration¶
All modules provided by this extension read their configuration from profiles:
- profile
A profile is a mapping under a top-level key in the minion configuration, minion pillar or master configuration (grains work also, but should not contain secrets such as
tokenorprivate_key). Functions and states use the profile namedgithubby default and accept aprofileargument to select a different one.
Profile parameters¶
A profile contains authentication credentials and default configuration the modules included in this Salt extension reference when running. The following keys can be specified in the profile:
tokenAccess token to authenticate with. Either this or GitHub App credentials (
app_id+ a private key) are required, mutually exclusively.
ownerDefault owner (organization or user) whose resources are managed with this profile. Defaults to the token’s user, if the token has one.
This value can be overridden per call via the
ownerargument.Needs to be set explicitly when the token does not have an associated resolvable user account such as GitHub App installation tokens. Required for GitHub App (
app_id) profiles.Added in version 1.1.0: Renamed from
org_name. The newgithub_repomodules can manage user repositories in addition to organization ones.org_namekeeps being supported as a legacy alias.
api_urlBase URL of the GitHub API. Set this when targeting a GitHub Enterprise Server instance, e.g.
https://github.example.com/api/v3. Defaults tohttps://api.github.com.
cacheKeep a persistent cross-process cache for specific API data, stored in the minion’s
cachedir. All entries are namespaced by a credential/API URL-derived identity, hence rotated credentials never serve stale data. For GitHub App profiles, the identity derives from the app’s identity (app_id+owner+permissions) rather than its short-lived installation tokens, so the cache survives token rotation. The data that is cached is either static or refreshed as soon as it changes. Defaults to true.Added in version 1.1.0.
Hint
Always cached are:
token-associated user handle (never changes)account name => account type lookups (should never change)
discovered GitHub App installation IDs (see
app_id)
When the
github resource typeis configured withgrains_files, file contents (including negative lookups) are also cached in relation to the repository’spushed_attimestamp (and automatically refreshed as soon as that timestamp changes).grains_refreshbypasses and rewrites the cached file contents. This especially benefitssalt-call --localsetups, where every invocation starts a fresh process and would otherwise refetch all file-based grains.
repo_nameThe default repository the
github_repofunctionsandstatesoperate on when norepo_nameis passed as an argument. Does not affect thegithubresource module.
allow_repo_privacy_changesAllow automated repository privacy modifications. Defaults to false since it can be dangerous to change the privacy of a repository in an automated way.
Multiple profiles¶
Any number of profiles can be defined and selected per call:
/etc/salt/minion.d/github.yml or /srv/pillar/github.sls with associated mapping in top.sls¶github:
token: hunter2
owner: my_organization
my_user:
token: hunter3
salt-call github_repo.list profile=my_user
Secret management¶
Profile values containing SDB URIs are rendered on access, which also works in pillar-sourced profiles:
/etc/salt/minion.d/sdb.yml¶osenv:
driver: env
/etc/salt/minion.d/github.yml or /srv/pillar/github.sls with associated mapping in top.sls¶# Requires a corresponding SDB profile in the minion configuration, see above
github:
token: sdb://osenv/GITHUB_TOKEN
owner: my_organization
GitHub App authentication¶
Added in version 1.1.0.
Instead of a static token, a profile can authenticate as a
GitHub App installation.
Hint
Two short-lived credentials are involved: an app JWT (signed with the
private key, freshly minted per app-scoped request, only used to
discover installations and mint tokens) and the installation access
tokens performing the actual API calls, which are valid for one hour
(fixed by GitHub) and never persisted by this extension. For explicit
cleanup – e.g. as the last step of an ephemeral CI run –
github.revoke_app_token
revokes the current token immediately.
app_idApp ID (or client ID) of a GitHub App to authenticate as, together with exactly one of
private_keyorprivate_key_pathand a requiredowner. Installation access tokens are minted (and refreshed before expiry) automatically, removing the need to pass short-lived tokens into the profile (e.g. viaactions/create-github-app-tokenin CI).The app’s installation on
owneris discovered via the API (an organization, falling back to user accounts) unless pinned withinstallation_id. The discovered ID is kept in the persistentcache, when enabled.Minted tokens carry all of the app’s granted permissions on all repositories the installation covers, unless restricted via
permissions(per token) or by installing the app on selected repositories only (per installation).Added in version 1.1.0.
private_keyPrivate key of the GitHub App (
app_id) in PEM format. Like all profile values, it can be an SDB URI, avoiding plain text keys in the configuration.Added in version 1.1.0.
private_key_pathPath to a local file containing the private key of the GitHub App (
app_id) in PEM format, as an alternative toprivate_key.Added in version 1.1.0.
installation_idID of the GitHub App’s (
app_id) installation onowner. Optional – when unset, it is discovered via the API.Added in version 1.1.0.
permissionsRestrict the installation access tokens minted for this GitHub App (
app_id) profile to a subset of the app’s granted permissions – a mapping of permission name to access level, e.g.contents: read. Defaults to all granted permissions.Allows profiles with different privileges to share a single app, e.g. a read-only profile for CI validation runs (
test=True) next to an unrestricted one for applying:github_readonly: app_id: 123456 private_key: sdb://osenv/GITHUB_APP_PRIVATE_KEY owner: my_organization permissions: metadata: read contents: read administration: read
Added in version 1.1.0.
Repository resource declaration¶
Added in version 1.1.0.
The github repository resource
(Salt 3008.3+, see the repository resources guide) is
declared in the managing minion’s pillar, under the subtree selected by
the resource_pillar_key minion option (default: resources).
Hint
The referenced profiles are resolved from the managing minion’s own
data, mirroring config.get’s lookup order – minion configuration,
grains, pillar and master configuration (which reaches the minion via
the master’s pillar_opts setting) – including SDB rendering.
profileName of the default profile for exposed
githubrepository resources. Defaults togithub.
ownersOwners (organizations or users) whose repositories to manage. Defaults to the default profile’s
owner(or the token’s user when unset). Either a plain list of owner names, or a mapping that overrides any of the other declaration keys per owner – e.g. a differentprofilewhen the repositories span credentials (separate tokens per organization, or a mix of github.com and a GitHub Enterprise Server instance), or per-owner repository selection:Plain list¶owners: - my-github-handle - my-org
Mapping with overrides for other declaration-level configs¶owners: my-github-handle: exclude: - not-this other-org: profile: other_github_org
Keys an owner does not override are inherited from the declaration level.
reposList of fnmatch patterns selecting the repositories to manage. Patterns containing a slash match the full name (
owner/repo), others the bare repository name. Defaults to all repositories. Can be overridden per owner in theownersmapping.
excludeList of fnmatch patterns excluding repositories, following the same matching rules as
reposand applied after it. Defaults to none. Can be overridden per owner in theownersmapping.
include_archivedInclude archived repositories. Defaults to false. Can be overridden per owner in the
ownersmapping.
grains_filesCustom resource grains sourced from YAML/JSON files inside each repository. A mapping of grain namespace to file specification – each namespace becomes a grain key next to the builtin ones (
id,owner,repo, …, which namespaces must not shadow). The special_namespace instead merges its keys into the root grains level; keys that already exist – the builtin identity grains or earlier namespaces – are never overwritten.pathFile path(s) inside the repository, a string or a list. All listed files are fetched; missing ones are skipped and the parsed mappings are shallow-merged in list order, earlier files winning.
includeOptional list of strings or single-key dicts selecting the exposed keys.
String entries are fnmatch patterns matched case-sensitively against colon-delimited key paths; a match includes the whole subtree, preserving nesting.
*crosses:boundaries.Single-entry mappings rename: the value at the exact source path (scalar or subtree, no patterns) is exposed under the new name as a flat or nested namespace key.
A plain mapping of new name to source path is shorthand for a list of mostly renames. Unset means everything is included.
See the [Full example config][full-example-config] for detailed syntax examples.
excludeOptional list of fnmatch patterns pruning matching key paths at any depth, applied after
include. Does not apply to renamed keys. Note that*also crosses:boundaries.
Can be overridden per owner in the
ownersmapping. Unlike the other keys, the override replaces the declaration-level value entirely (no merging) – an empty mapping thus disables custom grains for that owner.Important
These grains are controlled by anyone who can commit to the respective repository. Restrict the exposed keys via
includeallowlists and keep that trust model in mind when building targeting expressions. The builtin identity grains cannot be shadowed.
Minimal example config¶
This example showcases the minimally required config to use the modules and expose repositories as Salt resources.
/etc/salt/minion.d/github.yml or /srv/pillar/github.sls with associated mapping in top.sls¶# Specify the default token.
# If this is a PAT, it targets repositories owned by you, unless `owner` is specified explicitly.
github:
token: foobar
# Expose all your repositories as `github:your-handle/your-repo` resources.
resources:
github: {}
Full example config¶
This example showcases an intricate config for different actors/orgs and repo resource selection while avoiding to include plain text tokens in the config.
/etc/salt/minion.d/sdb.yml¶# SDB profile for the `env` SDB module.
# Exposes environment variables as `sdb://osenv/<ENV_VAR_NAME>` URIs.
osenv:
driver: env
# SDB profile for the `vault` SDB module.
# Exposes Vault secrets as `sdb://sdbvault/<mount>/<secret_path>?<secret_key>` URIs.
sdbvault:
driver: vault
/etc/salt/minion.d/github.yml or /srv/pillar/github.sls with associated mapping in top.sls¶# The default profile when not overridden in the function call
github:
token: sdb://sdbvault/secrets/my_github?token
allow_repo_privacy_changes: true
# This is resolved automatically if the token is associated with your user account:
# owner: my-github-handle
# Same token, but this profile defaults to organization scope when no `owner` is passed
my_github_org:
token: sdb://sdbvault/secrets/my_github?token
owner: my-org
# Different token and API endpoint for another organization.
other_enterprise_org:
api_url: https://github.example.com/api/v3
token: sdb://osenv/GITHUB_TOKEN
owner: other-org
# Expose select repositories as resources
resources:
github:
# By default, for any owner, only expose repositories that start with `foo-`,
# including archived ones.
include_archived: true
repos:
- foo-*
# Also try to load a file named `.github/data.json` from each repository and
# include all keys but those starting with an underscore in grains["data"]
grains_files:
data:
path: .github/data.json
exclude:
- "_*"
# Expose repositories specifically from these accounts.
owners:
# Use the defaults above. Exposed are: my-github-handle/foo-*
my-github-handle: {}
# Exclude archived ones and a specific one. Exposed are my-org/foo-*,
# but not the one repository named my-org/foo-not-this-repo.
my-org:
exclude:
- foo-not-this-repo
include_archived: false
# Expose repositories matching other-org/bar-* while using a different profile.
# Don't render any custom grains from files in these repositories.
other-org:
profile: other_enterprise_org
grains_files: {}
repos:
- bar-*
# Reset `repos` config to expose all repos.
# Showcase custom grains (in detail).
tiny-org:
# Reset repo selection to include all repos in tiny-org/*.
repos: {}
# Override the default custom file grains config completely
grains_files:
# When a repo has a `.github/grains.json` file, load it and merge
# select keys (by "glob" match) into the repository's grains (no namespace).
# You can rename keys by passing a single-key dict
# (no globs allowed in source or target).
# Explicit renames always win a slot.
# Note: inbuilt grains can never be overridden.
_:
path: .github/grains.json
include:
- team
- status
- nested:key
- 'include-all-*'
- '*-also-these'
- 'and-*-these'
- 'and:*-these' # a glob spans nesting levels
- some_key: renamed:from:a:deeply:nested:key
- some:nested:target: renamed:from:another:deeply:nested:key
# Try loading several paths and merge their data into the `data` namespace in grains.
# If more than one file specifies the same key, the *first* one wins.
# This one still excludes any keys that start with an underscore, but shows
# exclude/include can be specified as a simple string.
data:
path:
- .github/foo.json
- .github/bar.yml
exclude: _*
# Namespaces can be nested.
# `include` can be a mapping as a shorthand if most of your
# includes are renames. Regular patterns are still supported
# by specifying a falsy value.
nested:target:copier:
path: .copier-answers.yml
include:
template_version: _commit
nested:target: my_question
nested_source: my:question
just_keep_this_explicit_key:
keep_glob_*:stuff: ''