// deleteNetworkPolicyByID deletes the policy specified by the policyID func (l *KubeListener) deleteNetworkPolicyByID(policyID uint64) error { policyURL, err := l.restClient.GetServiceUrl("policy") if err != nil { return err } policyURL = fmt.Sprintf("%s/policies/%d", policyURL, policyID) log.Debugf("deleteNetworkPolicyByID: Deleting policy %d", policyID) deletedPolicy := common.Policy{} err = l.restClient.Delete(policyURL, nil, &deletedPolicy) if err != nil { switch err := err.(type) { default: return err case common.HttpError: if err.StatusCode == http.StatusNotFound { log.Warnf("deleteNetworkPolicyByID: Policy %d not found, ignoring", policyID) return nil } else { return err } } } log.Debugf("deleteNetworkPolicyByID: Deleted policy %s", deletedPolicy) return err }
// deleteDefaultPolicy deletes the policy, thus enabling isolation // effectively setting DefaultDeny to on. func deleteDefaultPolicy(o *v1.Namespace, l *KubeListener) { var err error // TODO this should be ExternalID, not Name... policyName := getDefaultPolicyName(o) policy := common.Policy{Name: policyName} policyURL, err := l.restClient.GetServiceUrl("policy") if err != nil { log.Errorf("In deleteDefaultPolicy :: Failed to find policy service: %s\n", err) log.Errorf("In deleteDefaultPolicy :: Failed to delete default policy: %s\n", policyName) return } policyURL = fmt.Sprintf("%s/find/policies/%s", policyURL, policy.Name) err = l.restClient.Get(policyURL, &policy) if err != nil { // An annotation to set isolation on may be issued multiple times. // If it already was reacted to and default policy was dropped, // then we don't do anything. log.Debugf("In deleteDefaultPolicy :: Failed to find policy %s: %s, ignoring\n", policyName, err) return } if err = l.deleteNetworkPolicyByID(policy.ID); err != nil { log.Errorf("In deleteDefaultPolicy :: Error :: failed to delete policy %d: %s\n", policy.ID, err) } }
// addDefaultPolicy adds the default policy which is to allow // all ingres. func addDefaultPolicy(o *v1.Namespace, l *KubeListener) { var err error // TODO this should be ExternalID, not Name... policyName := getDefaultPolicyName(o) // Before adding the default policy, see if it may already exist. policy := common.Policy{Name: policyName} policyURL, err := l.restClient.GetServiceUrl("policy") if err != nil { log.Errorf("In addDefaultPolicy :: Failed to find policy service: %s\n", err) log.Errorf("In addDefaultPolicy :: Failed to add default policy: %s\n", policyName) return } policyURL = fmt.Sprintf("%s/find/policies/%s", policyURL, policy.Name) err = l.restClient.Get(policyURL, &policy) if err == nil { // An annotation to set isolation off may be issued multiple // times and we already have the default policy caused by that in place. // So we just do not do anything. log.Infof("In addDefaultPolicy :: Policy %s (%d) already exists, ignoring\n", policy.Name, policy.ID) return } // Find tenant, to properly set up policy // TODO This really should be by external ID... tnt, err := l.resolveTenantByName(o.ObjectMeta.Name) if err != nil { log.Infof("In addDefaultPolicy :: Error :: failed to resolve tenant %s \n", err) return } romanaPolicy := &common.Policy{ Direction: common.PolicyDirectionIngress, Name: policyName, // ExternalID: externalID, AppliedTo: []common.Endpoint{{TenantNetworkID: &tnt.NetworkID}}, Ingress: []common.RomanaIngress{ common.RomanaIngress{ Peers: []common.Endpoint{{Peer: common.Wildcard}}, Rules: []common.Rule{{Protocol: common.Wildcard}}, }, }, } err = l.addNetworkPolicy(*romanaPolicy) switch err := err.(type) { default: log.Errorf("In addDefaultPolicy :: Error :: failed to create policy %s: %s\n", policyName, err) case nil: log.Debugf("In addDefaultPolicy: Succesfully created policy %s\n", policyName) case common.HttpError: if err.StatusCode == http.StatusConflict { log.Infof("In addDefaultPolicy ::Policy %s already exists.\n", policyName) } else { log.Errorf("In addDefaultPolicy :: Error :: failed to create policy %s: %s\n", policyName, err) } } }
// HandleDefaultPolicy handles isolation flag on a namespace by creating/deleting // default network policy. See http://kubernetes.io/docs/user-guide/networkpolicies/ func HandleDefaultPolicy(o *v1.Namespace, l *KubeListener) { var defaultDeny bool annotationKey := "net.beta.kubernetes.io/networkpolicy" if np, ok := o.ObjectMeta.Annotations[annotationKey]; ok { log.Infof("Handling default policy on a namespace %s, policy is now %s \n", o.ObjectMeta.Name, np) // Annotations are stored in the Annotations map as raw JSON. // So we need to parse it. isolationPolicy := struct { Ingress struct { Isolation string `json:"isolation"` } `json:"ingress"` }{} // TODO change to json.Unmarshal. Stas err := json.NewDecoder(strings.NewReader(np)).Decode(&isolationPolicy) if err != nil { log.Errorf("In HandleDefaultPolicy :: Error decoding annotation %s: %s", annotationKey, err) return } log.Debugf("Decoded to policy: %v", isolationPolicy) defaultDeny = isolationPolicy.Ingress.Isolation == "DefaultDeny" } else { log.Infof("Handling default policy on a namespace, no annotation detected assuming non isolated namespace\n") defaultDeny = false } if defaultDeny { deleteDefaultPolicy(o, l) } else { addDefaultPolicy(o, l) } }
// addNetworkPolicy adds the policy to the policy service. func (l *KubeListener) addNetworkPolicy(policy common.Policy) error { policyURL, err := l.restClient.GetServiceUrl("policy") if err != nil { return err } policyURL = fmt.Sprintf("%s/policies", policyURL) log.Debugf("Applying policy %s", policy) err = l.restClient.Post(policyURL, policy, &policy) if err != nil { return err } return nil }