Skip to content

Commit 5c27a97

Browse files
committed
Quadlet - new unit type .login
Implement a new unit for podman login Add support for AuthFile to container and kube units Allow linking between AuthFile and a login unit Signed-off-by: Ygal Blum <[email protected]>
1 parent 1f1618f commit 5c27a97

29 files changed

+600
-35
lines changed

cmd/quadlet/main.go

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -411,14 +411,14 @@ func loadUnitDropins(unit *parser.UnitFile, sourcePaths []string) error {
411411
return prevError
412412
}
413413

414-
func generateServiceFile(service *parser.UnitFile) error {
414+
func generateServiceFile(service *parser.UnitFile, fileMode fs.FileMode) error {
415415
Debugf("writing %q", service.Path)
416416

417417
service.PrependComment("",
418418
fmt.Sprintf("Automatically generated by %s", os.Args[0]),
419419
"")
420420

421-
f, err := os.Create(service.Path)
421+
f, err := os.OpenFile(service.Path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, fileMode)
422422
if err != nil {
423423
return err
424424
}
@@ -607,6 +607,8 @@ func generateUnitsInfoMap(units []*parser.UnitFile) map[string]*quadlet.UnitInfo
607607
// Prefill resouceNames for .pod files.
608608
// This is requires for referencing the pod from .container files
609609
resourceName = quadlet.GetPodResourceName(unit)
610+
case strings.HasSuffix(unit.Filename, ".login"):
611+
serviceName = quadlet.GetLoginServiceName(unit)
610612
default:
611613
Logf("Unsupported file type %q", unit.Filename)
612614
continue
@@ -706,11 +708,11 @@ func process() bool {
706708
sort.Slice(units, func(i, j int) bool {
707709
getOrder := func(i int) int {
708710
ext := filepath.Ext(units[i].Filename)
709-
order, ok := quadlet.SupportedExtensions[ext]
711+
extensionInfo, ok := quadlet.SupportedExtensions[ext]
710712
if !ok {
711713
return 0
712714
}
713-
return order
715+
return extensionInfo.Order
714716
}
715717
return getOrder(i) < getOrder(j)
716718
})
@@ -722,24 +724,33 @@ func process() bool {
722724
var service *parser.UnitFile
723725
var warnings, err error
724726

725-
switch {
726-
case strings.HasSuffix(unit.Filename, ".container"):
727+
ext := filepath.Ext(unit.Filename)
728+
extensionInfo, ok := quadlet.SupportedExtensions[ext]
729+
if !ok {
730+
Logf("Unsupported file type %q", unit.Filename)
731+
continue
732+
}
733+
734+
switch ext {
735+
case ".container":
727736
warnIfAmbiguousName(unit, quadlet.ContainerGroup)
728737
service, warnings, err = quadlet.ConvertContainer(unit, isUserFlag, unitsInfoMap)
729-
case strings.HasSuffix(unit.Filename, ".volume"):
738+
case ".volume":
730739
warnIfAmbiguousName(unit, quadlet.VolumeGroup)
731740
service, warnings, err = quadlet.ConvertVolume(unit, unit.Filename, unitsInfoMap, isUserFlag)
732-
case strings.HasSuffix(unit.Filename, ".kube"):
741+
case ".kube":
733742
service, err = quadlet.ConvertKube(unit, unitsInfoMap, isUserFlag)
734-
case strings.HasSuffix(unit.Filename, ".network"):
743+
case ".network":
735744
service, warnings, err = quadlet.ConvertNetwork(unit, unit.Filename, unitsInfoMap, isUserFlag)
736-
case strings.HasSuffix(unit.Filename, ".image"):
745+
case ".image":
737746
warnIfAmbiguousName(unit, quadlet.ImageGroup)
738747
service, err = quadlet.ConvertImage(unit, unitsInfoMap, isUserFlag)
739-
case strings.HasSuffix(unit.Filename, ".build"):
748+
case ".build":
740749
service, warnings, err = quadlet.ConvertBuild(unit, unitsInfoMap, isUserFlag)
741-
case strings.HasSuffix(unit.Filename, ".pod"):
750+
case ".pod":
742751
service, warnings, err = quadlet.ConvertPod(unit, unit.Filename, unitsInfoMap, isUserFlag)
752+
case ".login":
753+
service, err = quadlet.ConvertLogin(unit, unit.Filename, unitsInfoMap, isUserFlag)
743754
default:
744755
Logf("Unsupported file type %q", unit.Filename)
745756
continue
@@ -765,7 +776,7 @@ func process() bool {
765776
fmt.Printf("---%s---\n%s\n", service.Path, data)
766777
continue
767778
}
768-
if err := generateServiceFile(service); err != nil {
779+
if err := generateServiceFile(service, extensionInfo.ServiceFileMode); err != nil {
769780
reportError(fmt.Errorf("generating service file %s: %w", service.Path, err))
770781
}
771782
enableServiceFile(outputPath, service)

docs/source/markdown/podman-systemd.unit.5.md

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ Valid options for `[Container]` are listed below:
299299
| AddDevice=/dev/foo | --device /dev/foo |
300300
| AddHost=example\.com:192.168.10.11 | --add-host example.com:192.168.10.11 |
301301
| Annotation="XYZ" | --annotation "XYZ" |
302+
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
302303
| AutoUpdate=registry | --label "io.containers.autoupdate=registry" |
303304
| CgroupsMode=no-conmon | --cgroups=no-conmon |
304305
| ContainerName=name | --name name |
@@ -421,6 +422,16 @@ similar to `Environment`.
421422

422423
This key can be listed multiple times.
423424

425+
### `AuthFile=`
426+
427+
Path of the authentication file.
428+
429+
This is equivalent to the `--authfile` option.
430+
431+
Special Cases:
432+
433+
* If the `name` of the AuthFile ends with `.login`, Quadlet will use the authfile created by the corresponding `.login` file, and the generated systemd service contains a dependency on the `$name-login.service` (or the service name set in the `.login` file). Note that the corresponding `.login` file must exist and must include the `AuthFile` key.
434+
424435
### `AutoUpdate=`
425436

426437
Indicates whether the container will be auto-updated ([podman-auto-update(1)](podman-auto-update.1.md)). The following values are supported:
@@ -1240,6 +1251,7 @@ Valid options for `[Kube]` are listed below:
12401251

12411252
| **[Kube] options** | **podman kube play equivalent** |
12421253
| ------------------------------------| -----------------------------------------------------------------|
1254+
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
12431255
| AutoUpdate=registry | --annotation "io.containers.autoupdate=registry" |
12441256
| ConfigMap=/tmp/config.map | --config-map /tmp/config.map |
12451257
| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf |
@@ -1256,6 +1268,16 @@ Valid options for `[Kube]` are listed below:
12561268

12571269
Supported keys in the `[Kube]` section are:
12581270

1271+
### `AuthFile=`
1272+
1273+
Path of the authentication file.
1274+
1275+
This is equivalent to the `--authfile` option.
1276+
1277+
Special Cases:
1278+
1279+
* If the `name` of the AuthFile ends with `.login`, Quadlet will use the authfile created by the corresponding `.login` file, and the generated systemd service contains a dependency on the `$name-login.service` (or the service name set in the `.login` file). Note that the corresponding `.login` file must exist and must include the `AuthFile` key.
1280+
12591281
### `AutoUpdate=`
12601282

12611283
Indicates whether containers will be auto-updated ([podman-auto-update(1)](podman-auto-update.1.md)). AutoUpdate can be specified multiple times. The following values are supported:
@@ -1728,6 +1750,10 @@ Path of the authentication file.
17281750

17291751
This is equivalent to the `--authfile` option of `podman build`.
17301752

1753+
Special Cases:
1754+
1755+
* If the `name` of the AuthFile ends with `.login`, Quadlet will use the authfile created by the corresponding `.login` file, and the generated systemd service contains a dependency on the `$name-login.service` (or the service name set in the `.login` file). Note that the corresponding `.login` file must exist and must include the `AuthFile` key.
1756+
17311757
### `ContainersConfModule=`
17321758

17331759
Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option.
@@ -1963,7 +1989,12 @@ This is equivalent to the Podman `--arch` option.
19631989

19641990
Path of the authentication file.
19651991

1966-
This is equivalent to the Podman `--authfile` option.
1992+
This is equivalent to the `--authfile` option.
1993+
1994+
Special Cases:
1995+
1996+
* If the `name` of the AuthFile ends with `.login`, Quadlet will use the authfile created by the corresponding `.login` file, and the generated systemd service contains a dependency on the `$name-login.service` (or the service name set in the `.login` file). Note that the corresponding `.login` file must exist and must include the `AuthFile` key.
1997+
19671998

19681999
### `CertDir=`
19692000

@@ -2062,6 +2093,102 @@ Override the default architecture variant of the container image.
20622093

20632094
This is equivalent to the Podman `--variant` option.
20642095

2096+
## Login units [Login]
2097+
2098+
Login files are named with a `.login` extension and contain a section `[Login]` describing the
2099+
login command. The generated service is a one-time command that logs into a registry.
2100+
2101+
Using login units allows pulling images from private registries without having to login manually.
2102+
2103+
There is only one required key, `Registry`, which defines the URL of the registry to log into.
2104+
2105+
To avoid password leaking, Quadlet will set the permissions of the generated service file as 0600.
2106+
It is recommended to do the same for `.login` unit files.
2107+
2108+
Valid options for `[Login]` are listed below:
2109+
2110+
| **[Login] options** | **podman login** |
2111+
|-------------------------------------------------|----------------------------------------------------------------------|
2112+
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
2113+
| CertDir=/etc/certs | --cert-dir=/etc/certs |
2114+
| LogoutOnStop=true | Add ExecStopPost to log out of the registry when the unit is stopped |
2115+
| Password=mypassword | --password-stdin and set StandardInputText |
2116+
| PodmanArgs=--compat-auth-file=/etc/compat\.json | --compat-auth-file=/etc/registry/compat\.json |
2117+
| Registry=quai.io | podman login quai.io |
2118+
| Secret=mysecret | --secret=mysecret |
2119+
| ServiceName=name | Name the systemd unit `name.service` |
2120+
| TLSVerify=false | --tls-verify=false |
2121+
| Username=myuser | --username=myuser |
2122+
2123+
### `AuthFile=`
2124+
2125+
Path of the authentication file.
2126+
2127+
This field is mandatory when linking between an `AuthFile` key of a different unit and the `.login` unit.
2128+
2129+
This is equivalent to the Podman `--authfile` option.
2130+
2131+
### `CertDir=`
2132+
2133+
Use certificates at path (*.crt, *.cert, *.key) to connect to the registry.
2134+
2135+
This is equivalent to the Podman `--cert-dir` option.
2136+
2137+
2138+
### `LogoutOnStop=` (defaults to `false`)
2139+
2140+
When set to `true`, the logout will be called when the service is stopped.
2141+
2142+
### `Password=`
2143+
2144+
Use the password to connect to the registry.
2145+
In order to prevent password leak, instead of using the `--password` option,
2146+
Quadlet will set `--password-stdin` and use systemd `StandardInputText` to pass the data.
2147+
2148+
2149+
### `PodmanArgs=`
2150+
2151+
This key contains a list of arguments passed directly to the end of the `podman login` command
2152+
in the generated file. It can be used to access Podman features otherwise unsupported by the generator.
2153+
Since the generator is unaware of the unexpected interactions that can be caused by these arguments,
2154+
it is not recommended to use this option.
2155+
2156+
The format of this is a space separated list of arguments, which can optionally be individually
2157+
escaped to allow inclusion of whitespace and other control characters.
2158+
2159+
This key can be listed multiple times.
2160+
2161+
### `Registry=`
2162+
2163+
Use the URL of the registry to connect to. This key is mandatory.
2164+
2165+
This is equivalent to the last argument of `podman login`.
2166+
2167+
### `Secret=`
2168+
2169+
Use a podman secret for the credentials.
2170+
2171+
This is equivalent to the Podman `--secret` option.
2172+
2173+
### `ServiceName=`
2174+
2175+
By default, Quadlet will name the systemd service unit by appending `-login` to the name of the Quadlet.
2176+
Setting this key overrides this behavior by instructing Quadlet to use the provided name.
2177+
2178+
Note, the name should not include the `.service` file extension
2179+
2180+
### `TLSVerify=`
2181+
2182+
Require HTTPS and verification of certificates when contacting registries.
2183+
2184+
This is equivalent to the Podman `--tls-verify` option.
2185+
2186+
### `Username=`
2187+
2188+
Use the username to connect to the registry.
2189+
2190+
This is equivalent to the Podman `--username` option.
2191+
20652192
## Quadlet section [Quadlet]
20662193
Some quadlet specific configuration is shared between different unit types. Those settings
20672194
can be configured in the `[Quadlet]` section.
@@ -2241,6 +2368,26 @@ Options=iam_role,endpoint=${AWS_REGION},use_xattr,listobjectsv2,del_cache,use_ca
22412368
# `iam_role` assumes inside EC2, if not, Use `profile=` instead
22422369
```
22432370

2371+
Example for pulling from a private repository with a `.login` file
2372+
2373+
`private-repo.login`
2374+
```
2375+
[Login]
2376+
Registry=private-repo.example.com
2377+
AuthFile=/etc/auth/private-repo.json
2378+
TLSVerify=false
2379+
Username=myuser
2380+
Password=mypassword
2381+
LogoutOnStop=true
2382+
```
2383+
2384+
`app.container`
2385+
```
2386+
[Container]
2387+
Image=private-repo.example.com/myaccount/myapp:latest
2388+
AuthFile=private-repo.login
2389+
```
2390+
22442391
## SEE ALSO
22452392
**[systemd.unit(5)](https://www.freedesktop.org/software/systemd/man/systemd.unit.html)**,
22462393
**[systemd.service(5)](https://www.freedesktop.org/software/systemd/man/systemd.service.html)**,

0 commit comments

Comments
 (0)