| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package google
- import (
- "fmt"
- "regexp"
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/pinyinutils"
- "yunion.io/x/pkg/util/secrules"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/cloudmux/pkg/multicloud"
- )
- type SSecurityGroup struct {
- multicloud.SSecurityGroup
- GoogleTags
- gvpc *SGlobalNetwork
- Tag string
- Rules []SFirewall
- }
- func (self *SGoogleClient) GetFirewalls(network string, maxResults int, pageToken string) ([]SFirewall, error) {
- firewalls := []SFirewall{}
- params := map[string]string{"filter": "disabled = false"}
- resource := "global/firewalls"
- if len(network) > 0 {
- params["filter"] = fmt.Sprintf(`(disabled = false) AND (network="%s")`, network)
- }
- return firewalls, self._ecsListAll("GET", resource, params, &firewalls)
- }
- func (self *SGoogleClient) GetFirewall(id string) (*SFirewall, error) {
- firewall := &SFirewall{}
- return firewall, self.ecsGet("global/firewalls", id, firewall)
- }
- func (secgroup *SSecurityGroup) GetId() string {
- return secgroup.Tag
- }
- func (secgroup *SSecurityGroup) GetGlobalId() string {
- return secgroup.Tag
- }
- func (secgroup *SSecurityGroup) GetDescription() string {
- return ""
- }
- func (self *SSecurityGroup) GetTags() (map[string]string, error) {
- return nil, cloudprovider.ErrNotSupported
- }
- func (secgroup *SSecurityGroup) GetName() string {
- return secgroup.Tag
- }
- func (secgroup *SSecurityGroup) GetStatus() string {
- return api.SECGROUP_STATUS_READY
- }
- func (secgroup *SSecurityGroup) Refresh() error {
- rules, err := secgroup.gvpc.client.GetFirewalls(secgroup.gvpc.SelfLink, 0, "")
- if err != nil {
- return err
- }
- secgroup.Rules = []SFirewall{}
- for i := range rules {
- if len(rules[i].TargetTags) > 0 && rules[i].TargetTags[0] == secgroup.Tag {
- secgroup.Rules = append(secgroup.Rules, rules[i])
- }
- }
- if len(secgroup.Rules) == 0 {
- return cloudprovider.ErrNotFound
- }
- return nil
- }
- func (self *SSecurityGroup) Delete() error {
- for _, rule := range self.Rules {
- err := self.gvpc.client.ecsDelete(rule.SelfLink, nil)
- if err != nil {
- return errors.Wrapf(err, "delete")
- }
- }
- return nil
- }
- func (secgroup *SSecurityGroup) GetProjectId() string {
- return ""
- }
- func (secgroup *SSecurityGroup) GetVpcId() string {
- return secgroup.gvpc.GetGlobalId()
- }
- func (self *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
- ret := []cloudprovider.ISecurityGroupRule{}
- for i := range self.Rules {
- self.Rules[i].secgroup = self
- ret = append(ret, &self.Rules[i])
- }
- return ret, nil
- }
- func (self *SGoogleClient) CreateSecurityGroupRule(globalnetworkId, tag string, opts *cloudprovider.SecurityGroupRuleCreateOptions) (*SFirewall, error) {
- name := fmt.Sprintf("%s-%d-auto-%d", opts.String(), opts.Priority, time.Now().Unix())
- body := map[string]interface{}{
- "name": normalizeString(name),
- "description": opts.Desc,
- "priority": opts.Priority,
- "network": globalnetworkId,
- "direction": "INGRESS",
- "targetTags": []string{strings.ToLower(tag)},
- }
- if len(opts.CIDR) == 0 {
- opts.CIDR = "0.0.0.0/0"
- }
- if opts.Direction == secrules.DIR_OUT {
- body["direction"] = "EGRESS"
- body["destinationRanges"] = []string{opts.CIDR}
- } else {
- body["sourceRanges"] = []string{opts.CIDR}
- }
- protocol := strings.ToLower(opts.Protocol)
- if protocol == secrules.PROTO_ANY {
- protocol = "all"
- }
- actionInfo := []struct {
- IPProtocol string
- Ports []string
- }{
- {
- IPProtocol: protocol,
- },
- }
- if len(opts.Ports) > 0 {
- actionInfo[0].Ports = []string{opts.Ports}
- }
- if opts.Action == secrules.SecurityRuleDeny {
- body["denied"] = actionInfo
- } else {
- body["allowed"] = actionInfo
- }
- firwall := &SFirewall{}
- err := self.Insert("global/firewalls", jsonutils.Marshal(body), firwall)
- if err != nil {
- return nil, errors.Wrap(err, "region.Insert")
- }
- return firwall, nil
- }
- func (self *SSecurityGroup) CreateRule(opts *cloudprovider.SecurityGroupRuleCreateOptions) (cloudprovider.ISecurityGroupRule, error) {
- rule, err := self.gvpc.client.CreateSecurityGroupRule(self.gvpc.SelfLink, self.Tag, opts)
- if err != nil {
- return nil, err
- }
- rule.secgroup = self
- return rule, nil
- }
- func normalizeString(input string) string {
- // 1. 转换为小写
- lowerStr := strings.ToLower(input)
- lowerStr = strings.Replace(lowerStr, "_", "-", -1)
- lowerStr = pinyinutils.Text2Pinyin(lowerStr)
- // 2. 移除所有不符合要求的字符(只保留a-z、0-9和-)
- reg := regexp.MustCompile(`[^a-z0-9-]`)
- cleaned := reg.ReplaceAllString(lowerStr, "")
- // 3. 处理开头:如果不以字母开头,添加一个默认字母a
- if len(cleaned) == 0 || !regexp.MustCompile(`^[a-z]`).MatchString(cleaned) {
- cleaned = "a" + cleaned
- }
- // 4. 处理结尾:如果以连字符结尾,移除
- cleaned = regexp.MustCompile(`-$`).ReplaceAllString(cleaned, "")
- // 5. 限制长度为63个字符(域名标签的最大长度)
- if len(cleaned) > 63 {
- cleaned = cleaned[:63]
- // 确保截断后不以连字符结尾
- cleaned = regexp.MustCompile(`-$`).ReplaceAllString(cleaned, "")
- // 如果截断后为空,添加一个数字1
- if len(cleaned) == 0 {
- cleaned = "1"
- }
- }
- return cleaned
- }
- func (self *SGlobalNetwork) CreateISecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
- tag := normalizeString(opts.Name)
- secgroup := &SSecurityGroup{gvpc: self, Tag: tag}
- groups, err := self.GetISecurityGroups()
- if err != nil {
- return nil, err
- }
- for i := range groups {
- if groups[i].GetGlobalId() == secgroup.GetGlobalId() {
- return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "%s", secgroup.GetGlobalId())
- }
- }
- rule, err := secgroup.gvpc.client.CreateSecurityGroupRule(secgroup.gvpc.SelfLink, secgroup.Tag, &cloudprovider.SecurityGroupRuleCreateOptions{
- Desc: "default allow out",
- Priority: 65535,
- Protocol: secrules.PROTO_ANY,
- Direction: secrules.DIR_OUT,
- CIDR: "0.0.0.0/0",
- Action: secrules.SecurityRuleAllow,
- })
- if err != nil {
- return nil, errors.Wrapf(err, "CreateSecurityGroupRule")
- }
- secgroup.Rules = []SFirewall{*rule}
- return secgroup, nil
- }
|