更新配置自动化工具

栏目: Java · 发布时间: 6年前

内容简介:我们小创业公司使用的宽带是个人家庭宽带(申请企业宽带的成本很高,每月几千块),公网IP过一段时间就会变动,平时使用都没有什么影响,只有一点,阿里云上的服务都配置了安全组,只允许阿里云内网或者白名单IP访问,从而保障公司服务安全性。公司公网IP会动态变更,每一次变更之后都要修改安全组的ip配置,十分麻烦。来自攻城师的思考:每一次IP变动都打断了大家专心工作的心流(Flow)状态,而且登录阿里云控制台修改也很繁琐,修改安全组配置的IP名单,能不能自动化?大概瞄了一下阿里云相关的API,这事情可以搞。

  我们小创业公司使用的宽带是个人家庭宽带(申请企业宽带的成本很高,每月几千块),公网IP过一段时间就会变动,平时使用都没有什么影响,只有一点,阿里云上的服务都配置了安全组,只允许阿里云内网或者白名单IP访问,从而保障公司服务安全性。公司公网IP会动态变更,每一次变更之后都要修改安全组的ip配置,十分麻烦。

  来自攻城师的思考:每一次IP变动都打断了大家专心工作的心流(Flow)状态,而且登录阿里云控制台修改也很繁琐,修改安全组配置的IP名单,能不能自动化?

  大概瞄了一下阿里云相关的API,这事情可以搞。

动手实现

看看需要实现哪些功能:

  • 定时调度
  • 获取公司宽带的公网IP地址
  • 调用阿里云API刷新安全组的白名单IP

如何获取公司宽带的公网IP地址?

这个简单,市场上有很多ip查询的网站,比如 ip.cn,ipip.net ,你访问他们的网站,默认就会显示你的公网ip。

调用阿里云API没什么难度,只是工作量。

核心逻辑就是,获取当前公司ip,存储下来,每隔N分钟,再次获取公司当前ip,与之前记录对比,如果不同,则调用阿里云api,更新安全组白名单IP,最后存储新IP。否则什么也不做。

于是我创建了一个SpringBoot应用,为什么要创建一个java web应用?首先因为最熟悉java,其次是工程创建快速,使用简单,之前我实现了一个模版工程,可以快速创建SpringBoot应用,而且配置了常用的类库,非常方便。

一些核心功能实现:

@Component
public class ScheduleComp {

    Logger logger = LoggerFactory.getLogger(ScheduleComp.class);

    @Autowired
    RefreshSecurityRulService securityRulService;

    /**
     * 每隔3分钟检查一下
     */
    @Scheduled(cron = "0 */3 * * * ?")
    public void cornJob() {
        logger.warn(" >>cron执行....");
        securityRulService.refreshAll(false);
    }
}

securityRulService 的refreshAll()方法

public void refreshAll(boolean force) {
        String nowIp = getLocalIp();
        if (StringUtils.isEmpty(nowIp)) {
            logger.error("get current ip is empty! try next time...");
            return;
        }
        String oldIp = getCurrentIp();
        if (StringUtils.isEmpty(oldIp)) {
            throw new RuntimeException("current ip data is empty!");
        }
        if (StringUtils.equals(nowIp, oldIp) && !force) {
            logger.warn("same ip, nothing todo");
            return;
        }
        ecsRefreshSecurityRuleService.refreshAll(nowIp, oldIp);

        updateCurrentIp(nowIp);
    }

getLocalIp() 的实现:

public static String getLocalIp() {
        String ip = getIpCN();
  			...
          
        return ip;
    }

public static String getIpCN() {
        //<p>您现在的 IP:<code>114.0.1.2</code>
        return getLocalIp("http://ip.cn", "<p>您现在的 IP:<code>");
    }


public static String getLocalIp(String url, String prefix) {
        Request request = new Request.Builder()
                .get()
                .url(url)
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                String regexPatten = prefix + "((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))).){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))";
                Pattern pattern = Pattern.compile(regexPatten);
                String resp = response.body().string();
                Matcher matcher = pattern.matcher(resp);
                if (matcher.find()) {
                    String matchStr = matcher.group(0);
                    return matchStr.replace(prefix, "");
                }
            }
            response.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }

这里通过 ip.cn 获取本机的公网地址。

还可以配置其他网站,防止ip.cn挂掉而导致服务失败。

getCurrentIp 的实现很简单,从本地文件读取上次记录的ip地址。

public String getCurrentIp() {
        File file = new File("ip.txt");
        if (!file.exists()) {
            throw new RuntimeException("cannot find ip data!");
        }
        try {
            BufferedReader bufferedReader =
                    new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            String strLine = bufferedReader.readLine();
            bufferedReader.close();
            return strLine.trim();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

采用文件存储是最简单直接的方式。更新文件内容的代码:

private void updateCurrentIp(String ip) {
        if (StringUtils.isEmpty(ip))
            return;
        File file = new File("ip.txt");
        file.delete();
        try {
            file.createNewFile();
            BufferedWriter bufferedWriter =
                    new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
            bufferedWriter.write(ip.trim());
            bufferedWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

刷新阿里云安全组配置的逻辑:

public void refreshAll(String nowIp, String oldIp) {

        List<SecurityRuleDO> newSecurityRuleDOList = new ArrayList<>(testServer(nowIp));
        for (SecurityRuleDO securityRuleDO : newSecurityRuleDOList) {
            refresh(securityRuleDO);

        }

        if (!StringUtils.equals(nowIp, oldIp)) {
            List<SecurityRuleDO> oldSecurityRuleDOList = new ArrayList<>();
            oldSecurityRuleDOList.addAll(testServer(oldIp));
            for (SecurityRuleDO securityRuleDO : oldSecurityRuleDOList) {
                deleteOld(securityRuleDO);
            }

        }
    }

private List<SecurityRuleDO> testServer(String ip) {
        List<SecurityRuleDO> securityRuleDOList = new ArrayList<>();
        SecurityRuleDO securityRuleDO = new SecurityRuleDO();
        securityRuleDO.sourceIp = ip;
        securityRuleDO.groupId = "YourECSGroupId";
        securityRuleDO.ipProtocol = "tcp";
        securityRuleDO.portRange = "yourPort/yourPort";
        securityRuleDOList.add(securityRuleDO);
				...
        return securityRuleDOList;
    }


public boolean refresh(SecurityRuleDO securityRuleDO) {
        AuthorizeSecurityGroupRequest request =
                new AuthorizeSecurityGroupRequest();
        request.setSecurityGroupId(securityRuleDO.groupId);
        request.setIpProtocol(securityRuleDO.ipProtocol);
        request.setPortRange(securityRuleDO.portRange);
        request.setNicType(securityRuleDO.nicType);
        request.setPolicy("accept");
        request.setSourceCidrIp(securityRuleDO.sourceIp);

        try {
            AuthorizeSecurityGroupResponse response = client.getAcsResponse(request);
            String requestId = response.getRequestId();
            System.out.println(requestId);
            return true;
        } catch (ClientException e) {
            e.printStackTrace();
            return false;
        }
    }

public boolean deleteOld(SecurityRuleDO securityRuleDO) {
        RevokeSecurityGroupRequest request = new RevokeSecurityGroupRequest();
        request.setSecurityGroupId(securityRuleDO.groupId);
        request.setIpProtocol(securityRuleDO.ipProtocol);
        request.setPortRange(securityRuleDO.portRange);
        request.setNicType(securityRuleDO.nicType);
        request.setPolicy("accept");
        request.setSourceCidrIp(securityRuleDO.sourceIp);

        try {
            RevokeSecurityGroupResponse response = client.getAcsResponse(request);
            String requestId = response.getRequestId();
            System.out.println(requestId);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

其中client的初始化:

DefaultProfile profile = DefaultProfile.getProfile(reginId, appkey, secret);
                    client = new DefaultAcsClient(profile);

小问题

定时3分钟刷新有个小问题,就是有极小的概率,发生IP变更但是还没有及时刷新安全组的配置。怎么办,再加一个主动刷新的接口呗:

@RestController
public class RefreshSecurityRuleController {
    @Autowired
    RefreshSecurityRulService securityRulService;

    @GetMapping("/ip")
    public String getMyIp() {
        return securityRulService.getLocalIp();
    }

    @GetMapping("/fresh")
    public String forceFresh() {
        securityRulService.refreshAll(true);
        return "done!";
    }

}

其中的 /fresh 强制刷新IP。还附赠了一个接口,获取公司当前的IP。

这个小应用部署在公司局域网内,一直工作的很好,再也不用烦心IP变动这些琐事。

直到有一次,ip.cn 网站挂了。挂了很久,我们就增加了从 ip.tool.chinaz.com 网站获取IP。

收工。


以上所述就是小编给大家介绍的《更新配置自动化工具》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java Servlet & JSP Cookbook

Java Servlet & JSP Cookbook

Bruce W. Perry / O'Reilly Media / 2003-12-1 / USD 49.99

With literally hundreds of examples and thousands of lines of code, the Java Servlet and JSP Cookbook yields tips and techniques that any Java web developer who uses JavaServer Pages or servlets will ......一起来看看 《Java Servlet & JSP Cookbook》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具