// DeleteTrustedKeyPrefix deletes the prefix trusted key identified by fingerprint. func (ks *Keystore) DeleteTrustedKeyPrefix(prefix, fingerprint string) error { acname, err := types.NewACName(prefix) if err != nil { return err } return os.Remove(path.Join(ks.LocalPrefixPath, acname.String(), fingerprint)) }
func handleAppAnnotation(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) { defer r.Body.Close() n := mux.Vars(r)["name"] k, err := types.NewACIdentifier(n) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "App annotation name %q is not a valid AC Identifier", n) return } n = mux.Vars(r)["app"] an, err := types.NewACName(n) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "App name %q is not a valid AC Name", n) return } merged := mergeAppAnnotations(im, pm, an) v, ok := merged.Get(k.String()) if !ok { w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, "App annotation %q not found", k) return } w.Header().Add("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) w.Write([]byte(v)) }
// getAppName returns the app name to enter // If one was supplied in the flags then it's simply returned // If the PM contains a single app, that app's name is returned // If the PM has multiple apps, the names are printed and an error is returned func getAppName(p *pod) (*types.ACName, error) { if flagAppName != "" { return types.NewACName(flagAppName) } // figure out the app name, or show a list if multiple are present b, err := ioutil.ReadFile(common.PodManifestPath(p.path())) if err != nil { return nil, fmt.Errorf("error reading pod manifest: %v", err) } m := schema.PodManifest{} if err = m.UnmarshalJSON(b); err != nil { return nil, fmt.Errorf("unable to load manifest: %v", err) } switch len(m.Apps) { case 0: return nil, fmt.Errorf("pod contains zero apps") case 1: return &m.Apps[0].Name, nil default: } stderr("Pod contains multiple apps:") for _, ra := range m.Apps { stderr("\t%v", ra.Name) } return nil, fmt.Errorf("specify app using \"rkt enter --app= ...\"") }
// NewAppFromString takes a command line app parameter and returns a map of labels. // // Example app parameters: // example.com/reduce-worker:1.0.0 // example.com/reduce-worker,channel=alpha,label=value func NewAppFromString(app string) (*App, error) { var ( name string labels map[types.ACName]string ) app = strings.Replace(app, ":", ",version=", -1) app = "name=" + app v, err := url.ParseQuery(strings.Replace(app, ",", "&", -1)) if err != nil { return nil, err } labels = make(map[types.ACName]string, 0) for key, val := range v { if len(val) > 1 { return nil, fmt.Errorf("label %s with multiple values %q", key, val) } if key == "name" { name = val[0] continue } labelName, err := types.NewACName(key) if err != nil { return nil, err } labels[*labelName] = val[0] } a, err := NewApp(name, labels) if err != nil { return nil, err } return a, nil }
// StoreTrustedKeyPrefix stores the contents of public key r as a prefix trusted key. func (ks *Keystore) StoreTrustedKeyPrefix(prefix string, r io.Reader) (string, error) { acname, err := types.NewACName(prefix) if err != nil { return "", err } return storeTrustedKey(path.Join(ks.LocalPrefixPath, acname.String()), r) }
func mergeManifests(manifests []schema.ImageManifest) schema.ImageManifest { // FIXME(iaguis) we take app layer's manifest as the final manifest for now manifest := manifests[0] manifest.Dependencies = nil layerIndex := -1 for i, l := range manifest.Labels { if l.Name.String() == "layer" { layerIndex = i } } if layerIndex != -1 { manifest.Labels = append(manifest.Labels[:layerIndex], manifest.Labels[layerIndex+1:]...) } // this can't fail because the old name is legal nameWithoutLayerID, _ := appctypes.NewACName(stripLayerID(manifest.Name.String())) manifest.Name = *nameWithoutLayerID // once the image is squashed, we don't need a pathWhitelist manifest.PathWhitelist = nil return manifest }
// MaskTrustedKeySystemPrefix masks the system prefix trusted key identified by fingerprint. func (ks *Keystore) MaskTrustedKeySystemPrefix(prefix, fingerprint string) (string, error) { acname, err := types.NewACName(prefix) if err != nil { return "", err } dst := path.Join(ks.LocalPrefixPath, acname.String(), fingerprint) return dst, ioutil.WriteFile(dst, []byte(""), 0644) }
func (ks *Keystore) loadKeyring(prefix string) (openpgp.KeyRing, error) { acname, err := types.NewACName(prefix) if err != nil { return nil, err } var keyring openpgp.EntityList trustedKeys := make(map[string]*openpgp.Entity) prefixRoot := strings.Split(acname.String(), "/")[0] paths := []struct { root string fullPath string }{ {ks.SystemRootPath, ks.SystemRootPath}, {ks.LocalRootPath, ks.LocalRootPath}, {path.Join(ks.SystemPrefixPath, prefixRoot), path.Join(ks.SystemPrefixPath, acname.String())}, {path.Join(ks.LocalPrefixPath, prefixRoot), path.Join(ks.LocalPrefixPath, acname.String())}, } for _, p := range paths { err := filepath.Walk(p.root, func(path string, info os.FileInfo, err error) error { if err != nil && !os.IsNotExist(err) { return err } if info == nil { return nil } if info.IsDir() { switch { case strings.HasPrefix(p.fullPath, path): return nil default: return filepath.SkipDir } } // Remove trust for default keys. if info.Size() == 0 { delete(trustedKeys, info.Name()) return nil } entity, err := entityFromFile(path) if err != nil { return err } trustedKeys[fingerprintToFilename(entity.PrimaryKey.Fingerprint)] = entity return nil }) if err != nil { return nil, err } } for _, v := range trustedKeys { keyring = append(keyring, v) } return keyring, nil }
func NewApp(name string, labels map[types.ACName]string) (*App, error) { if labels == nil { labels = make(map[types.ACName]string, 0) } acn, err := types.NewACName(name) if err != nil { return nil, err } return &App{ Name: *acn, Labels: labels, }, nil }
func checkSignature(ks *Keystore, prefix string, signed, signature io.Reader) (*openpgp.Entity, error) { acname, err := types.NewACName(prefix) if err != nil { return nil, err } keyring, err := ks.loadKeyring(acname.String()) if err != nil { return nil, fmt.Errorf("keystore: error loading keyring %v", err) } entities, err := openpgp.CheckArmoredDetachedSignature(keyring, signed, signature) if err == io.EOF { // otherwise, the client failure is just "EOF", which is not helpful return nil, fmt.Errorf("keystore: no signatures found") } return entities, err }
func handleAppAnnotations(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) { defer r.Body.Close() n := mux.Vars(r)["app"] an, err := types.NewACName(n) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "App name %q is not a valid AC Name", n) return } w.Header().Add("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) for _, annot := range mergeAppAnnotations(im, pm, an) { fmt.Fprintln(w, string(annot.Name)) } }
func handleAppID(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest, im *schema.ImageManifest) { defer r.Body.Close() n := mux.Vars(r)["app"] an, err := types.NewACName(n) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "App name %q is not a valid AC Name", n) return } w.Header().Add("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) app := pm.Apps.Get(*an) if app == nil { // This is impossiple as we have already checked that // the image manifest is not nil in the parent function. panic("could not find app in manifest!") } w.Write([]byte(app.Image.ID.String())) }
func handlePodAnnotation(w http.ResponseWriter, r *http.Request, pm *schema.PodManifest) { defer r.Body.Close() k, err := types.NewACName(mux.Vars(r)["name"]) if err != nil { w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, "Pod annotation is not a valid AC Name") return } v, ok := pm.Annotations.Get(k.String()) if !ok { w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, "Pod annotation (%v) not found", k) return } w.Header().Add("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) w.Write([]byte(v)) }
func (al *appMount) Set(s string) error { mount := schema.Mount{} // this is intentionally made similar to types.VolumeFromString() // TODO(iaguis) use MakeQueryString() when appc/spec#520 is merged m, err := url.ParseQuery(strings.Replace(s, ",", "&", -1)) if err != nil { return err } for key, val := range m { if len(val) > 1 { return fmt.Errorf("label %s with multiple values %q", key, val) } switch key { case "volume": mv, err := types.NewACName(val[0]) if err != nil { return fmt.Errorf("invalid volume name %q in --mount flag %q: %v", val[0], s, err) } mount.Volume = *mv case "target": mount.Path = val[0] default: return fmt.Errorf("unknown mount parameter %q", key) } } as := (*apps.Apps)(al) if as.Count() == 0 { as.Mounts = append(as.Mounts, mount) } else { app := as.Last() app.Mounts = append(app.Mounts, mount) } return nil }
func (pl *portList) Set(s string) error { parts := strings.SplitN(s, ":", 2) if len(parts) != 2 { return fmt.Errorf("%q is not in name:port format", s) } name, err := types.NewACName(parts[0]) if err != nil { return fmt.Errorf("%q is not a valid port name: %v", parts[0], err) } port, err := strconv.ParseUint(parts[1], 10, 16) if err != nil { return fmt.Errorf("%q is not a valid port number", parts[1]) } p := types.ExposedPort{ Name: *name, HostPort: uint(port), } *pl = append(*pl, p) return nil }
func GenerateManifest(layerData types.DockerImageData, dockerURL *types.ParsedDockerURL) (*schema.ImageManifest, error) { dockerConfig := layerData.Config genManifest := &schema.ImageManifest{} appURL := "" // omit docker hub index URL in app name if dockerURL.IndexURL != defaultIndex { appURL = dockerURL.IndexURL + "/" } appURL += dockerURL.ImageName + "-" + layerData.ID appURL, err := appctypes.SanitizeACName(appURL) if err != nil { return nil, err } name, err := appctypes.NewACName(appURL) if err != nil { return nil, err } genManifest.Name = *name acVersion, err := appctypes.NewSemVer(schemaVersion) if err != nil { panic("invalid appc spec version") } genManifest.ACVersion = *acVersion genManifest.ACKind = appctypes.ACKind(schema.ImageManifestKind) var labels appctypes.Labels var parentLabels appctypes.Labels layer, _ := appctypes.NewACName("layer") labels = append(labels, appctypes.Label{Name: *layer, Value: layerData.ID}) tag := dockerURL.Tag version, _ := appctypes.NewACName("version") labels = append(labels, appctypes.Label{Name: *version, Value: tag}) if layerData.OS != "" { os, _ := appctypes.NewACName("os") labels = append(labels, appctypes.Label{Name: *os, Value: layerData.OS}) parentLabels = append(parentLabels, appctypes.Label{Name: *os, Value: layerData.OS}) if layerData.Architecture != "" { arch, _ := appctypes.NewACName("arch") parentLabels = append(parentLabels, appctypes.Label{Name: *arch, Value: layerData.Architecture}) } } genManifest.Labels = labels if dockerConfig != nil { exec := getExecCommand(dockerConfig.Entrypoint, dockerConfig.Cmd) if exec != nil { user, group := parseDockerUser(dockerConfig.User) var env appctypes.Environment for _, v := range dockerConfig.Env { parts := strings.SplitN(v, "=", 2) env.Set(parts[0], parts[1]) } app := &appctypes.App{ Exec: exec, User: user, Group: group, Environment: env, WorkingDirectory: dockerConfig.WorkingDir, } genManifest.App = app } } if layerData.Parent != "" { parentAppNameString := dockerURL.IndexURL + "/" + dockerURL.ImageName + "-" + layerData.Parent parentAppNameString, err := appctypes.SanitizeACName(parentAppNameString) if err != nil { return nil, err } parentAppName, err := appctypes.NewACName(parentAppNameString) if err != nil { return nil, err } genManifest.Dependencies = append(genManifest.Dependencies, appctypes.Dependency{App: *parentAppName, Labels: parentLabels}) } return genManifest, nil }
func patchManifest(im *schema.ImageManifest) error { if patchName != "" { name, err := types.NewACName(patchName) if err != nil { return err } im.Name = *name } if patchExec != "" { im.App.Exec = strings.Split(patchExec, " ") } if patchUser != "" { im.App.User = patchUser } if patchGroup != "" { im.App.Group = patchGroup } if patchCaps != "" { app := im.App if app == nil { return fmt.Errorf("no app in the manifest") } isolator := app.Isolators.GetByName(types.LinuxCapabilitiesRetainSetName) if isolator != nil { return fmt.Errorf("isolator already exists") } // Instantiate a Isolator with the content specified by the --capability // parameter. // TODO: Instead of creating a JSON and then unmarshalling it, the isolator // should be instantiated directory. But it requires a constructor, see: // https://github.com/appc/spec/issues/268 capsList := strings.Split(patchCaps, ",") caps := fmt.Sprintf(`"set": ["%s"]`, strings.Join(capsList, `", "`)) isolatorStr := getIsolatorStr(types.LinuxCapabilitiesRetainSetName, caps) isolator = &types.Isolator{} err := isolator.UnmarshalJSON([]byte(isolatorStr)) if err != nil { return err } app.Isolators = append(app.Isolators, *isolator) } if patchMounts != "" { app := im.App if app == nil { return fmt.Errorf("no app in the manifest") } mounts := strings.Split(patchMounts, ":") for _, m := range mounts { mountPoint, err := types.MountPointFromString(m) if err != nil { return fmt.Errorf("cannot parse mount point %q", m) } app.MountPoints = append(app.MountPoints, *mountPoint) } } return nil }