<div dir="ltr"><div><div>2014-03-25 18:14 GMT+01:00 Stephen Gallagher &lt;<a href="mailto:sgallagh@redhat.com">sgallagh@redhat.com</a>&gt;:<br>&gt; On 03/24/2014 05:02 PM, Miloslav Trmač wrote:<br>&gt;&gt; 2014-03-19 14:47 GMT+01:00 Stephen Gallagher &lt;<a href="mailto:sgallagh@redhat.com">sgallagh@redhat.com</a><br>
&gt;&gt; Wouldn&#39;t it be cleaner to have generic ValidateSettings(settings)<br>&gt;&gt; DeployRole(settings) as the abstraction used by the &quot;universal&quot;<br>&gt;&gt; clients (with &quot;settings&quot; possibly having some universal settings,<br>
&gt;&gt; like our favorite firewall_enabled_after_deploy, but mostly<br>&gt;&gt; role-specific, only using a standard format, perhaps JSON or some<br>&gt;&gt; object graph with similar capabilities)?<br>&gt;<br>&gt; That&#39;s an idea. I&#39;m not sure it&#39;s doing anything other than moving the<br>
&gt; problem to the settings object instead of the method call, but *shrug*.<br><br>Right, it would be even better to provide role-specific APIs (or a generic API with schema enforcement) to change values within the settings object :)&nbsp; in order to make typos in settings names obvious, and that point it is really similar.<br>
<br>It does only one structurally significant thing: encode the &quot;settings format&quot; (JSON/whatever) as a canonical way to describe/dump/persistently store role deployment configuration, giving the API users precisely the same facilities they have during installation.<br>
<br><br>&gt;&gt; * methods: * GetFirewallPorts: list of port/protocol pairs that the<br>&gt;&gt; Role needs<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; I&#39;d much rather have FirewallRestriction enum (LocalhostOnly,<br>&gt;&gt; Unrestricted, Complex) or something like that, or, if we decided<br>
&gt;&gt; to depend on firewalld, an object reference to a firewalld service.<br>&gt;&gt; Roles will be asking for ICMP, new IP protocols, and whatnot, and<br>&gt;&gt; we don&#39;t need to start with that complexity in the API and the<br>
&gt;&gt; clients.<br>&gt;<br>&gt; Sorry, that was a little thin. Could you go into a bit more detail<br>&gt; here, please?<br><br>Stepping back a little, the role <i>implementation</i> and <i>external API</i> should be different.&nbsp; The implementation obviously does need to actually contain port numbers and the like somewhere, but I don&#39;t think we want them in the role&#39;s public API.<br>
<br></div>The reason is that this introduces too much complexity into the API, at a level that isn&#39;t interesting to many important users of the API.&nbsp; The complexity is in all the things a role might need (TCP ports, UDP ports, IP protocols, specific multicast addresses, perhaps even conntrack modules), and the presumed callers of a &quot;Role deploy API&quot; just don&#39;t care, they want the role deployed firewalled/not firewalled, and a service dashboard needs to to know whether it has been firewalled.&nbsp; Receiving a list of half-a-dozen different individual firewall concepts to check isn&#39;t all that helpful, the public API should be able to give a simple yes/no answer (well, a &quot;yes/no/&quot;it&#39;s complicated&quot; answer, which are the badly-explained LocalhostOnly/Unrestricted/Complex values above).<br>
<br></div>Depending on firewalld, it seems simplest for roles to provide firewalld services, and refer to callers to them.&nbsp; We might still want a simple facade above, providing only the ability set LocalhostOnly/Unrestricted, and to receive current status as one of the three values.&nbsp; That would be appropriate for a simple dashboard, more detailed management would be done on the firewalld service object directly using the firewalld API.<br>
<div><div><div><br><br>&gt;&gt; * AddCertificateAuthority: &nbsp; &nbsp; &nbsp; Add a certificate authority to<br>&gt;&gt; this domain controller * EnableDisableDNS: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Enable or<br>&gt;&gt; disable the DNS server on this server<br>
&gt;&gt;<br>&gt;&gt; This would of course work. &nbsp;A philosophical question, though: would<br>&gt;&gt; we rather move to closer to the &quot;cattle&quot; model, i.e.<br>&gt;&gt;<br>&gt;&gt; settings = role.GetCurrentSettings() settings.enableDNS = False<br>
&gt;&gt; role.Redeploy(settings)<br>&gt;&gt; ?<br>&gt;&gt;<br>&gt;&gt; A &quot;redeploy&quot; is more work for the role, having to compare the<br>&gt;&gt; settings with current deployment and apply them, but it also ensure<br>
&gt;&gt; that that code path works; with the individual configuration<br>&gt;&gt; modification operations, the roles could still provide a<br>&gt;&gt; GetCurrentSettings method, but we would have two completely<br>&gt;&gt; separate paths (EnableDisableDNS vs. Deploy) to test, and the risk<br>
&gt;&gt; of them diverging.<br>&gt;&gt;<br>&gt;<br>&gt; Hmm, but redeploy may not be possible (or idempotent) for all possible<br>&gt; setting changes.<br><br></div><div>It&#39;s always possible to delete all data and start fresh :)&nbsp; An API to redeploy that doesn&#39;t delete data needs the option to fail, sure&mdash;but any functionality that can be done using a GetValue/SetValue-like API should be equally possible to do using a Redeploy model; in the role-already-deployed case, it&#39;s just a series of<br>
&gt; if (settings.option_name != role.GetValue(option_name))<br></div><div>&gt; &nbsp;&nbsp; role.setValue(option_name, settings.option_name)<br></div><div>and<br></div><div>&gt; if (settings.immutable_option_name != role.GetValue(immutable_option_name)<br>
</div><div>&gt;&nbsp;&nbsp;&nbsp; fail;<br></div><div>snippets.<br></div><div><br></div><div>So semantically the two are sort of equivalent, this is primarily a matter of how we want to encourage the users to work with the system: keep a pet and modify it over time with the API, or have a settings file managed in a VCS somewhere and use the API only to sync the VCS and the deployment?<br>
</div><div><br><br>&gt;&gt; If we provide a limited firewall facade so that Fedora Server can<br>&gt;&gt; work without firewalld, IMHO it should literally be the simplest<br>&gt;&gt; possible &quot;role.FirewallPreventsNonLocalhostAccess&quot; value; not even<br>
&gt;&gt; listing the ports involved. &nbsp;If we provide something closer to a<br>&gt;&gt; full-featured D-Bus API firewall, we might just as well require<br>&gt;&gt; firewalld directly instead of writing a firewalld competitor.<br>
&gt;<br>&gt; I think my original statement failed to get my point across, but I<br>&gt; think I was pretty much saying the same thing you are.<br></div><div>I think so too.<br></div><div><br>&gt; First of all,<br>&gt; we *did* agree to use firewalld as the proper solution. I just meant<br>
&gt; that in terms of defining the Role-firewall interop, it should *not*<br>&gt; try to be a complete set of firewall rules. For that, we should allow<br>&gt; a Role to have a &#39;managed_firewall=False&#39; setting[1] or something like<br>
&gt; it, and that admins would be expected to handle the firewall<br>&gt; appropriately through firewalld/iptables. But if we *are* managing it,<br>&gt; it&#39;s probably acceptable for it to be essentially either blocked or<br>
&gt; allowed on a whitelist of interfaces (&#39;lo&#39; being just a special case).<br>&gt; Anyone requiring more control than that should set<br>&gt; managed_firewall=False and do it themselves.<br><br></div><div>We could even have the managed_firewall=False implicit, as &quot;service is not assigned to the Public or Drop zones&quot; (... which would leave even the &quot;allow on a whitelist of interfaces&quot; case up to non-Role-API firewalld calls; I have no idea whether this would be appropriate).<br>
</div><div>&nbsp;&nbsp;&nbsp; Mirek<br></div></div></div></div>