Пример #1
0
func handleCredentials(apiVersion, subpath string, c *ec2metaproxy.ContainerService, w http.ResponseWriter, r *http.Request) {
	resp, err := instanceServiceClient.RoundTrip(NewGET(baseURL + "/" + apiVersion + "/meta-data/iam/security-credentials/"))

	if err != nil {
		log.Error("Error requesting creds path for API version ", apiVersion, ": ", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		w.WriteHeader(resp.StatusCode)
		return
	}

	clientIP := remoteIP(r.RemoteAddr)
	role, err := c.RoleForIP(clientIP)

	if err != nil {
		log.Error(clientIP, " ", err)
		http.Error(w, "An unexpected error getting container role", http.StatusInternalServerError)
		return
	}

	roleName := role.Arn.RoleName()

	if len(subpath) == 0 {
		w.Write([]byte(roleName))
	} else if !strings.HasPrefix(subpath, roleName) || (len(subpath) > len(roleName) && subpath[len(roleName)-1] != '/') {
		// An idiosyncrasy of the standard EC2 metadata service:
		// Subpaths of the role name are ignored. So long as the correct role name is provided,
		// it can be followed by a slash and anything after the slash is ignored.
		w.WriteHeader(http.StatusNotFound)
	} else {
		creds, err := json.Marshal(&MetadataCredentials{
			Code:            "Success",
			LastUpdated:     role.LastUpdated,
			Type:            "AWS-HMAC",
			AccessKeyID:     role.Credentials.AccessKey,
			SecretAccessKey: role.Credentials.SecretKey,
			Token:           role.Credentials.Token,
			Expiration:      role.Credentials.Expiration,
		})

		if err != nil {
			log.Error("Error marshaling credentials: ", err)
			w.WriteHeader(http.StatusInternalServerError)
		} else {
			w.Write(creds)
		}
	}
}
Пример #2
0
func (t *ContainerService) syncContainers() {
	log.Info("Synchronizing state with running docker containers")
	apiContainers, err := t.docker.ListContainers(docker.ListContainersOptions{
		All:    false, // only running containers
		Size:   false, // do not need size information
		Limit:  0,     // all running containers
		Since:  "",    // not applicable
		Before: "",    // not applicable
	})

	if err != nil {
		log.Error("Error listing running containers: ", err)
		return
	}

	containerIPMap := make(map[string]*ContainerInfo)
	containerIDMap := make(map[string]string)

	for _, apiContainer := range apiContainers {
		container, err := t.docker.InspectContainer(apiContainer.ID)

		if err != nil {
			log.Error("Error inspecting container: ", apiContainer.ID, ": ", err)
			continue
		}

		shortContainerID := apiContainer.ID[:6]
		containerIP := container.NetworkSettings.IPAddress

		roleArn, roleErr := getRoleArnFromEnv(container.Config.Env, t.defaultRoleArn)

		if roleArn.Empty() && roleErr == nil {
			roleErr = fmt.Errorf("No role defined for container %s: image=%s", shortContainerID, container.Config.Image)
		}

		log.Infof("Container: id=%s image=%s role=%s", shortContainerID, container.Config.Image, roleArn)

		containerIPMap[containerIP] = &ContainerInfo{
			ContainerID:      apiContainer.ID,
			ShortContainerID: shortContainerID,
			SessionName:      generateSessionName(container),
			LastUpdated:      time.Time{},
			Error:            roleErr,
			RoleArn:          roleArn,
		}

		containerIDMap[apiContainer.ID] = containerIP
	}

	t.containerIPMap = containerIPMap
	t.containerIDMap = containerIDMap
}
Пример #3
0
func main() {
	kingpin.CommandLine.Help = "Docker container EC2 metadata service."
	kingpin.Parse()

	defer log.Flush()
	configureLogging(*verboseOpt)

	auth, err := aws.GetAuth("", "", "", time.Time{})

	if err != nil {
		panic(err)
	}

	containerService := ec2metaproxy.NewContainerService(dockerClient(), *defaultRole, auth)

	// Proxy non-credentials requests to primary metadata service
	http.HandleFunc("/", logHandler(func(w http.ResponseWriter, r *http.Request) {
		match := credsRegex.FindStringSubmatch(r.URL.Path)
		if match != nil {
			handleCredentials(match[1], match[2], containerService, w, r)
			return
		}

		proxyReq, err := http.NewRequest(r.Method, fmt.Sprintf("%s%s", baseURL, r.URL.Path), r.Body)

		if err != nil {
			log.Error("Error creating proxy http request: ", err)
			http.Error(w, "An unexpected error occurred communicating with Amazon", http.StatusInternalServerError)
			return
		}

		copyHeaders(proxyReq.Header, r.Header)
		resp, err := instanceServiceClient.RoundTrip(proxyReq)

		if err != nil {
			log.Error("Error forwarding request to EC2 metadata service: ", err)
			http.Error(w, "An unexpected error occurred communicating with Amazon", http.StatusInternalServerError)
			return
		}

		defer resp.Body.Close()

		copyHeaders(w.Header(), resp.Header)
		w.WriteHeader(resp.StatusCode)
		if _, err := io.Copy(w, resp.Body); err != nil {
			log.Warn("Error copying response content from EC2 metadata service: ", err)
		}
	}))

	log.Critical(http.ListenAndServe(*serverAddr, nil))
}