render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
43fe83
From 87ab326e99c0c6b556bfff54a6e4e9bd09faa495 Mon Sep 17 00:00:00 2001
43fe83
Message-Id: <87ab326e99c0c6b556bfff54a6e4e9bd09faa495.1377873638.git.jdenemar@redhat.com>
43fe83
From: "Daniel P. Berrange" <berrange@redhat.com>
43fe83
Date: Tue, 13 Aug 2013 11:38:26 +0100
43fe83
Subject: [PATCH] Add info about access control checks into API reference
43fe83
43fe83
For https://bugzilla.redhat.com/show_bug.cgi?id=700443
43fe83
43fe83
So that app developers / admins know what access control checks
43fe83
are performed for each API, this patch extends the API docs
43fe83
generator to include details of the ACLs for each.
43fe83
43fe83
The gendispatch.pl script is extended so that it generates
43fe83
a simple XML describing ACL rules, eg.
43fe83
43fe83
  <aclinfo>
43fe83
    ...
43fe83
    <api name='virConnectNumOfDomains'>
43fe83
      <check object='connect' perm='search_domains'/>
43fe83
      <filter object='domain' perm='getattr'/>
43fe83
    </api>
43fe83
    <api name='virDomainAttachDeviceFlags'>
43fe83
      <check object='domain' perm='write'/>
43fe83
      <check object='domain' perm='save' flags='!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE'/>
43fe83
      <check object='domain' perm='save' flags='VIR_DOMAIN_AFFECT_CONFIG'/>
43fe83
    </api>
43fe83
    ...
43fe83
  </aclinfo>
43fe83
43fe83
The newapi.xsl template loads the XML files containing the ACL
43fe83
rules and generates a short block of HTML for each API describing
43fe83
the parameter checks and return value filters (if any).
43fe83
43fe83
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
43fe83
(cherry picked from commit 664ab2801dfcb8e72fc4408cc50c279bf74e47a2)
43fe83
---
43fe83
 .gitignore             |  3 +++
43fe83
 docs/libvirt.css       | 14 +++++++++++
43fe83
 docs/newapi.xsl        | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
43fe83
 src/Makefile.am        | 22 ++++++++++++++--
43fe83
 src/rpc/gendispatch.pl | 59 ++++++++++++++++++++++++++++++++++++++++---
43fe83
 5 files changed, 160 insertions(+), 6 deletions(-)
43fe83
43fe83
diff --git a/docs/libvirt.css b/docs/libvirt.css
43fe83
index 8a00d12..ed67b2f 100644
43fe83
--- a/docs/libvirt.css
43fe83
+++ b/docs/libvirt.css
43fe83
@@ -477,3 +477,17 @@ dl.variablelist > dt {
43fe83
 dl.variablelist > dt:after {
43fe83
     content: ": ";
43fe83
 }
43fe83
+
43fe83
+table.acl {
43fe83
+    margin: 1em;
43fe83
+    border-spacing: 0px;
43fe83
+    border: 1px solid #ccc;
43fe83
+}
43fe83
+
43fe83
+table.acl tr, table.acl td {
43fe83
+    padding: 0.3em;
43fe83
+}
43fe83
+
43fe83
+table.acl thead {
43fe83
+    background: #ddd;
43fe83
+}
43fe83
diff --git a/docs/newapi.xsl b/docs/newapi.xsl
43fe83
index d5b210e..58f12eb 100644
43fe83
--- a/docs/newapi.xsl
43fe83
+++ b/docs/newapi.xsl
43fe83
@@ -29,6 +29,69 @@
43fe83
   <xsl:variable name="htmldir">html</xsl:variable>
43fe83
   <xsl:variable name="href_base">../</xsl:variable>
43fe83
 
43fe83
+  <xsl:variable name="acls">
43fe83
+    <xsl:copy-of select="document('../src/libvirt_access.xml')/aclinfo/api"/>
43fe83
+  </xsl:variable>
43fe83
+  <xsl:variable name="qemuacls">
43fe83
+    <xsl:copy-of select="document('../src/libvirt_access_qemu.xml')/aclinfo/api"/>
43fe83
+  </xsl:variable>
43fe83
+  <xsl:variable name="lxcacls">
43fe83
+    <xsl:copy-of select="document('../src/libvirt_access_lxc.xml')/aclinfo/api"/>
43fe83
+  </xsl:variable>
43fe83
+
43fe83
+  <xsl:template name="aclinfo">
43fe83
+    <xsl:param name="api"/>
43fe83
+
43fe83
+    <xsl:if test="count(exsl:node-set($acls)/api[@name=$api]/check) > 0">
43fe83
+      
Access control parameter checks
43fe83
+      
43fe83
+        
43fe83
+          
43fe83
+            Object
43fe83
+            Permission
43fe83
+            Condition
43fe83
+          
43fe83
+        
43fe83
+        <xsl:apply-templates select="exsl:node-set($acls)/api[@name=$api]/check" mode="acl"/>
43fe83
+      
43fe83
+    </xsl:if>
43fe83
+    <xsl:if test="count(exsl:node-set($acls)/api[@name=$api]/filter) > 0">
43fe83
+      
Access control return value filters
43fe83
+      
43fe83
+        
43fe83
+          
43fe83
+            Object
43fe83
+            Permission
43fe83
+          
43fe83
+        
43fe83
+        <xsl:apply-templates select="exsl:node-set($acls)/api[@name=$api]/filter" mode="acl"/>
43fe83
+      
43fe83
+    </xsl:if>
43fe83
+  </xsl:template>
43fe83
+
43fe83
+  <xsl:template match="check" mode="acl">
43fe83
+    
43fe83
+      <xsl:value-of select="@object"/>
43fe83
+      <xsl:value-of select="@perm"/>
43fe83
+      <xsl:choose>
43fe83
+        <xsl:when test="@flags">
43fe83
+          <xsl:value-of select="@flags"/>
43fe83
+        </xsl:when>
43fe83
+        <xsl:otherwise>
43fe83
+          -
43fe83
+        </xsl:otherwise>
43fe83
+      </xsl:choose>
43fe83
+    
43fe83
+  </xsl:template>
43fe83
+
43fe83
+  <xsl:template match="filter" mode="acl">
43fe83
+    
43fe83
+      <xsl:value-of select="@object"/>
43fe83
+      <xsl:value-of select="@perm"/>
43fe83
+    
43fe83
+  </xsl:template>
43fe83
+
43fe83
+
43fe83
   <xsl:template name="navbar">
43fe83
     <xsl:variable name="previous" select="preceding-sibling::file[1]"/>
43fe83
     <xsl:variable name="next" select="following-sibling::file[1]"/>
43fe83
@@ -553,6 +616,11 @@
43fe83
         </xsl:if>
43fe83
       
43fe83
     </xsl:if>
43fe83
+    
43fe83
+      <xsl:call-template name="aclinfo">
43fe83
+        <xsl:with-param name="api" select="$name"/>
43fe83
+      </xsl:call-template>
43fe83
+    
43fe83
   </xsl:template>
43fe83
 
43fe83
   <xsl:template match="exports" mode="toc">
43fe83
diff --git a/src/Makefile.am b/src/Makefile.am
43fe83
index 12ca204..8c6f068 100644
43fe83
--- a/src/Makefile.am
43fe83
+++ b/src/Makefile.am
43fe83
@@ -826,6 +826,11 @@ ACCESS_DRIVER_SYM_FILES = \
43fe83
 		libvirt_access_qemu.syms \
43fe83
 		libvirt_access_lxc.syms
43fe83
 
43fe83
+ACCESS_DRIVER_API_FILES = \
43fe83
+		libvirt_access.xml \
43fe83
+		libvirt_access_qemu.xml \
43fe83
+		libvirt_access_lxc.xml
43fe83
+
43fe83
 ACCESS_DRIVER_SOURCES = \
43fe83
 		access/viraccessperm.h access/viraccessperm.c \
43fe83
 		access/viraccessmanager.h access/viraccessmanager.c \
43fe83
@@ -1492,8 +1497,8 @@ EXTRA_DIST += $(ACCESS_DRIVER_POLKIT_SOURCES)
43fe83
 endif
43fe83
 
43fe83
 
43fe83
-BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED)
43fe83
-CLEANFILES += $(ACCESS_DRIVER_GENERATED)
43fe83
+BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_API_FILES)
43fe83
+CLEANFILES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_API_FILES)
43fe83
 
43fe83
 libvirt_access.syms: $(srcdir)/rpc/gendispatch.pl \
43fe83
 			$(REMOTE_PROTOCOL) Makefile.am
43fe83
@@ -1508,6 +1513,19 @@ libvirt_access_lxc.syms: $(srcdir)/rpc/gendispatch.pl \
43fe83
 	$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclsym \
43fe83
 	  lxc LXC $(LXC_PROTOCOL) > $@
43fe83
 
43fe83
+libvirt_access.xml: $(srcdir)/rpc/gendispatch.pl \
43fe83
+			$(REMOTE_PROTOCOL) Makefile.am
43fe83
+	$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \
43fe83
+	  remote REMOTE $(REMOTE_PROTOCOL) > $@
43fe83
+libvirt_access_qemu.xml: $(srcdir)/rpc/gendispatch.pl \
43fe83
+			$(QEMU_PROTOCOL) Makefile.am
43fe83
+	$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \
43fe83
+	  qemu QEMU $(QEMU_PROTOCOL) > $@
43fe83
+libvirt_access_lxc.xml: $(srcdir)/rpc/gendispatch.pl \
43fe83
+			$(LXC_PROTOCOL) Makefile.am
43fe83
+	$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclapi \
43fe83
+	  lxc LXC $(LXC_PROTOCOL) > $@
43fe83
+
43fe83
 $(srcdir)/access/viraccessapicheck.h: $(srcdir)/rpc/gendispatch.pl \
43fe83
 			$(REMOTE_PROTOCOL) Makefile.am
43fe83
 	$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclheader \
43fe83
diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl
43fe83
index 8f41771..ac0c7ab 100755
43fe83
--- a/src/rpc/gendispatch.pl
43fe83
+++ b/src/rpc/gendispatch.pl
43fe83
@@ -41,8 +41,8 @@ my $res = GetOptions("mode=s" => \$mode);
43fe83
 die "cannot parse command line options" unless $res;
43fe83
 
43fe83
 die "unknown mode '$mode', expecting 'client', 'server', " .
43fe83
-    "'aclheader', 'aclbody', 'aclsym' or 'debug'"
43fe83
-    unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|debug)$/;
43fe83
+    "'aclheader', 'aclbody', 'aclsym', 'aclapi' or 'debug'"
43fe83
+    unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|aclapi|debug)$/;
43fe83
 
43fe83
 my $structprefix = shift or die "missing struct prefix argument";
43fe83
 my $procprefix = shift or die "missing procedure prefix argument";
43fe83
@@ -351,6 +351,13 @@ if ($mode eq "aclsym") {
43fe83
 # Automatically generated by gendispatch.pl.
43fe83
 # Do not edit this file.  Any changes you make will be lost.
43fe83
 __EOF__
43fe83
+} elsif ($mode eq "aclapi") {
43fe83
+    print <<__EOF__;
43fe83
+
43fe83
+  -  Automatically generated by gendispatch.pl.
43fe83
+  -  Do not edit this file.  Any changes you make will be lost.
43fe83
+  -->
43fe83
+__EOF__
43fe83
 } else {
43fe83
     print <<__EOF__;
43fe83
 /* Automatically generated by gendispatch.pl.
43fe83
@@ -1641,7 +1648,8 @@ elsif ($mode eq "client") {
43fe83
     }
43fe83
 } elsif ($mode eq "aclheader" ||
43fe83
          $mode eq "aclbody" ||
43fe83
-         $mode eq "aclsym") {
43fe83
+         $mode eq "aclsym" ||
43fe83
+         $mode eq "aclapi") {
43fe83
     my %generate = map { $_ => 1 } @autogen;
43fe83
     my @keys = keys %calls;
43fe83
 
43fe83
@@ -1667,6 +1675,7 @@ elsif ($mode eq "client") {
43fe83
         foreach my $hdr (@headers) {
43fe83
             print "#include \"$hdr\"\n";
43fe83
         }
43fe83
+        print "\n";
43fe83
     } elsif ($mode eq "aclbody") {
43fe83
         my $header = shift;
43fe83
         print "#include <config.h>\n";
43fe83
@@ -1676,8 +1685,12 @@ elsif ($mode eq "client") {
43fe83
         print "#include \"virerror.h\"\n";
43fe83
         print "\n";
43fe83
         print "#define VIR_FROM_THIS VIR_FROM_ACCESS\n";
43fe83
+        print "\n";
43fe83
+    } elsif ($mode eq "aclapi") {
43fe83
+        print "<aclinfo>\n";
43fe83
+    } else {
43fe83
+        print "\n";
43fe83
     }
43fe83
-    print "\n";
43fe83
 
43fe83
     foreach (@keys) {
43fe83
         my $call = $calls{$_};
43fe83
@@ -1699,6 +1712,8 @@ elsif ($mode eq "client") {
43fe83
                 print $apiname . "CheckACL;\n";
43fe83
             }
43fe83
             print $apiname . "EnsureACL;\n";
43fe83
+        } elsif ($mode eq "aclapi") {
43fe83
+            &generate_aclapi($call);
43fe83
         } else {
43fe83
             &generate_acl($call, $call->{acl}, "Ensure");
43fe83
             if (defined $call->{aclfilter}) {
43fe83
@@ -1835,5 +1850,41 @@ elsif ($mode eq "client") {
43fe83
                 print "}\n\n";
43fe83
             }
43fe83
         }
43fe83
+
43fe83
+        sub generate_aclapi {
43fe83
+            my $call = shift;
43fe83
+
43fe83
+            my $apiname = "vir" . $call->{ProcName};
43fe83
+            if ($structprefix eq "qemu") {
43fe83
+                $apiname =~ s/virDomain/virDomainQemu/;
43fe83
+            } elsif ($structprefix eq "lxc") {
43fe83
+                $apiname =~ s/virDomain/virDomainLxc/;
43fe83
+            }
43fe83
+
43fe83
+            print "  <api name='$apiname'>\n";
43fe83
+
43fe83
+            my $acl = $call->{acl};
43fe83
+            foreach (@{$acl}) {
43fe83
+                my @bits = split /:/;
43fe83
+                print "    
43fe83
+                if (defined $bits[2]) {
43fe83
+                    print " flags='$bits[2]'";
43fe83
+                }
43fe83
+                print "/>\n";
43fe83
+            }
43fe83
+
43fe83
+            my $aclfilter = $call->{aclfilter};
43fe83
+            foreach (@{$aclfilter}) {
43fe83
+                my @bits = split /:/;
43fe83
+                print "    <filter object='$bits[0]' perm='$bits[1]'/>\n";
43fe83
+            }
43fe83
+
43fe83
+            print "  </api>\n";
43fe83
+        }
43fe83
+
43fe83
+    }
43fe83
+
43fe83
+    if ($mode eq "aclapi") {
43fe83
+        print "</aclinfo>\n";
43fe83
     }
43fe83
 }
43fe83
-- 
43fe83
1.8.3.2
43fe83